Cloud Client
authorAndrii Shtompel <a.shtompel@samsung.com>
Mon, 12 Sep 2016 09:15:36 +0000 (18:15 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Mon, 12 Sep 2016 09:30:55 +0000 (09:30 +0000)
Implemented:
1. Cloud Client itself with menu and folders structure
2. CRL/ACL requests according latest spec

[Patch #2] Remove OCPayload to ACL/CRL convertion.
           Convert OCpayload back to char * and
           Use ACL/CRL resource functions to parse and update DB
[Patch #3] Add sync to menu and start userRequests as thread
[Patch #4] Save minor changes before merge both clients
[Patch #5] Merge CSR to this cloud client
[Patch #6] Clean-up changes. Merged cloud client works
[Patch #7] Save minor changes before move to cloud-interface branch
[Patch #8] Store private data
[Patch #9] Implement CRL on device according latest spec
[Patch #10] Minor Crl on device fixes
[Patch #11] Handle review comments
[Patch #12] Implement ACL get info on device according spec
            Remove OC_EXPORT from headers
[Patch #13] Fix CBOR encoding
[Patch #14] Crl last update, crl db changes, fix build error
[Patch #15] Crl Get/Post are fully implemented
[Patch #16] Acl fix uri path'es
[Patch #17] PKIX interface to SRM
[Patch #18] CRL rcsn fix (use String Array instead of String)
[Patch #19] ACL callbacks implemetation (parse and print recv data)
[Patch #20] Complete ACL callbacks
[Patch #21] Update Menu UI
[Patch #22] ACL uid's length fixes
[Patch #23] ACL ace request + CRL encoding fix
[Patch #24] Fix crash when receive empty aclist
[Patch #25] Set public data default encoding to DER
            Fix CRL initialization
[Patch #26, 27] Restore #24
[Patch #28] Fix build error related to PKIX
[Patch #29] ACL few fixes, clean-up code, add comments
[Patch #32] Clean-up csr + handle all review comments
[Patch #34] Revert ocpayload.c changes
[Patch #35] Fix build without WITH_TCP, CRL/ACL clean-up, error on exit
[Patch #37] Fix private data encoding
[Patch #38] Test build on Windows
[Patch #40] Remove accidental changes
[Patch #41] TLS sample fix
[Patch #42] CRL changes to use CBORPayload() functions
[Patch #43] ACL changes to use CBORpayload() + printAcl() + minor fixes
[Patch #44] Added extern C for external linkage to C++
[Patch #45] Revert #44 + acl fix
[Patch #47] Implement OC_LOG_PAYLOAD to show nested objects and arrays
[Patch #48] Fix review comments
            Add dynamic cipher based on SVR
            Change close notify to alert
[Patch #49] Add rootcer.crt and SaveTrustCert in cloudClient sample
[Patch #50] Change cipher priority and add choose cipher option in sample
[Patch #51] Remove accidental changes
[Patch #52] Add RSA cipher selection
[Patch #53] Huge changes in API and handlers to provide it to external team
[Patch #54] Minor fix, clean-up, add comments
[Patch #55] Resoved issue for save TrustCert with PEM in cloudClient sample
[Patch #56] UpdateACE fix, add CoAPs selection to Menu
[Patch #57] Few ACL requests fix, now all of them are working
[Patch #58] Add db file to command-line args + few fixes
[Patch #60] Add alert messages
[Patch #61] Fix cipher selection
[Patch #62] Fix Svace warnings
[Patch #63] Fix acl db issue. Create CBORpayloadToAcl2() for cloud response
            Because in latest spec its wrong we need this workaround
[Patch #64] Fix service folder build error when secured enabled
[Patch #65] Implement responses to cloud cpp wrapper API
[Patch #66] Minor fix to cloud cpp wrapper responses
[Patch #67] Fix Cbor allocation when credresource increase
[Patch #68] Revert wrong changes made in Patch #64
[Patch #69] Remove wrong changes in other SConscript files
[Patch #70] Fix minor build error
[Patch #71] Remove wrong changes from 2 source files + clean-up Sconscripts
[Patch #72] Return back credresource.c + fix crlresource.c for tizen
[Patch #73] Return back richdk scons
[Patch #74] Disable build stack samples without SECURED=1
[Patch #75] Fix OTM PIN
[Patch #76] Fix conflict
[Patch #77,78] Fix tizen build error
[Patch #80] Remove changes in secure stack samples
[Patch #81] Add ours headers to doxygen, update comments, add static
[Patch #83] Fix conflicts with master
[Patch #84] Add Discovery + Get/Put/Post device-to-device requests
            Separate most sample source code to cloud folder
[Patch #86] Arduino build fix
[Patch #87] Resolve merge conflict

Change-Id: Ib83b14a40d49df3b62dd5a1863777c8a5504a4e5
Signed-off-by: Jonsgung Lee<js126.lee@samsung.com>
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Signed-off-by: Dmitriy Zhuravlev <d.zhuravlev@samsung.com>
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Signed-off-by: Joonghwan Lee<jh05.lee@samsung.com>
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Signed-off-by: Joonghwan Lee<jh05.lee@samsung.com>
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Signed-off-by: Dmitriy Zhuravlev <d.zhuravlev@samsung.com>
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Signed-off-by: Oleksandr Dmytrenko <o.dmytrenko@samsung.com>
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/10785
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
Tested-by: Randeep Singh <randeep.s@samsung.com>
51 files changed:
resource/SConscript
resource/csdk/connectivity/api/casecurityinterface.h
resource/csdk/connectivity/inc/ca_adapter_net_tls.h
resource/csdk/connectivity/src/SConscript
resource/csdk/connectivity/src/adapter_util/ca_adapter_net_tls.c
resource/csdk/connectivity/src/caconnectivitymanager.c
resource/csdk/security/SConscript
resource/csdk/security/include/internal/aclresource.h
resource/csdk/security/include/internal/credresource.h
resource/csdk/security/include/internal/crlresource.h
resource/csdk/security/include/internal/srmresourcestrings.h
resource/csdk/security/include/pkix_interface.h [new file with mode: 0644]
resource/csdk/security/include/securevirtualresourcetypes.h
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/include/cloud/occloudprovisioning.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/cloud/utils.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/internal/secureresourceprovider.h
resource/csdk/security/provisioning/include/pmutility.h
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/cloud.dat [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud/cloudAuth.c [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud/cloudAuth.h [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud/cloudCommon.h [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud/cloudDiscovery.c [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud/cloudDiscovery.h [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud/cloudWrapper.c [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloud/cloudWrapper.h [new file with mode: 0644]
resource/csdk/security/provisioning/sample/cloudClient.c [new file with mode: 0644]
resource/csdk/security/provisioning/sample/rootca.crt [new file with mode: 0644]
resource/csdk/security/provisioning/src/cloud/aclgroup.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/cloud/aclid.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/cloud/aclinvite.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/cloud/crl.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/cloud/csr.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/cloud/utils.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/src/aclresource.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/crlresource.c
resource/csdk/security/src/pkix_interface.c [new file with mode: 0644]
resource/csdk/security/src/psinterface.c
resource/csdk/security/src/resourcemanager.c
resource/csdk/security/src/secureresourcemanager.c
resource/csdk/security/src/srmresourcestrings.c
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/include/payload_logging.h
resource/csdk/stack/src/ocpayload.c
resource/docs/c-doc/Doxyfile
service/easy-setup/mediator/richsdk/SConscript

index 1542c2f..e3f217e 100644 (file)
@@ -69,8 +69,9 @@ if target_os in ['linux', 'windows']:
        SConscript('csdk/stack/test/linux/SConscript')
        SConscript('csdk/stack/samples/linux/SimpleClientServer/SConscript')
 
-       # Build secure samples
-       SConscript('csdk/stack/samples/linux/secure/SConscript')
+        if env.get('SECURED') == '1':
+               # Build secure samples
+               SConscript('csdk/stack/samples/linux/secure/SConscript')
 
        # Build C/C++ unit tests
        SConscript('unit_tests.scons')
index e9a27cb..bae8653 100644 (file)
@@ -95,6 +95,14 @@ CAResult_t CARegisterDTLSCredentialsHandler(CAGetDTLSPskCredentialsHandler GetDT
 
 #ifdef __WITH_TLS__
 /**
+ * This internal callback is used by CA layer to
+ * retrieve all credential types from SRM
+ *
+ * @param[out]  list of enabled credential types for CA handshake
+ *
+ */
+typedef void (*CAgetCredentialTypesHandler)(bool * list);
+/**
  * Binary structure containing PKIX related info
  * own certificate chain, public key, CA's and CRL's
  */
@@ -111,6 +119,12 @@ typedef struct
 } PkiInfo_t;
 
 /**
+ * Register callback to receive credential types.
+ * @param[in] credTypesCallback callback to get cerdential types
+ * @return ::CA_STATUS_OK
+ */
+CAResult_t CAregisterGetCredentialTypesCallback(CAgetCredentialTypesHandler credTypesCallback);
+/**
  * Register callback to receive the result of TLS handshake.
  * @param[in] tlsHandshakeCallback callback for get tls handshake result
  * @return ::CA_STATUS_OK
index 449e79e..130c126 100644 (file)
@@ -59,8 +59,13 @@ void CAsetTlsAdapterCallbacks(CAPacketReceivedCallback recvCallback,
                               CATransportAdapter_t type);
 
 /**
- * Register callback to get TLS PSK credentials.
- * @param[in]  credCallback    callback to get TLS PSK credentials.
+ * Register callback to get credentials types.
+ * @param[in]   credTypesCallback    callback to get credential types.
+ */
+void CAsetCredentialTypesCallback(CAgetCredentialTypesHandler credTypesCallback);
+/**
+ * Register callback to get credential types.
+ * @param[in]  typesCallback    callback to get credential types.
  */
 void CAsetTlsCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback);
 
index 44921de..b49e9c2 100644 (file)
@@ -74,6 +74,7 @@ if env.get('DTLS_WITH_X509') == '1':
        env.AppendUnique(CA_SRC = pkix_src)
 
 if ((secured == '1') and (with_tcp == True)):
+       env.AppendUnique(CPPPATH = [os.path.join(src_dir, 'resource', 'csdk', 'security', 'include')])
        env.AppendUnique(CPPDEFINES = ['__WITH_TLS__'])
        tls_path = 'extlibs/mbedtls';
        tls_headers_path = 'mbedtls/include';
index 36f0234..66a5f97 100644 (file)
@@ -21,6 +21,7 @@
 #define _GNU_SOURCE
 
 #include <stddef.h>
+#include <stdbool.h>
 #include "ca_adapter_net_tls.h"
 #include "cacommon.h"
 #include "caipinterface.h"
@@ -85,7 +86,7 @@
  * @def MMBED_TLS_DEBUG_LEVEL
  * @brief Logging level for mbedTLS library
  */
-#define MBED_TLS_DEBUG_LEVEL (4) // Verbose
+#define MBED_TLS_DEBUG_LEVEL (4)
 
 /**
  * @def TLS_MSG_BUF_LEN
  */
 #define MASTER_SECRET_LEN (48)
 
+/**@def TLS_CLOSE_NOTIFY(peer, ret)
+ *
+ * Notifies of existing \a peer about closing TLS connection.
+ *
+ * @param[in] peer remote peer
+ * @param[in] ret used internaly
+ */
 #define TLS_CLOSE_NOTIFY(peer, ret)                                                                \
 do                                                                                                 \
 {                                                                                                  \
     ret = mbedtls_ssl_close_notify(&peer->ssl);                                                    \
 } while (MBEDTLS_ERR_SSL_WANT_WRITE == ret)
 
+/**@def TLS_RET_HANDSHAKE_RES(peer)
+ *
+ * Sets handshake result for callback.
+ *
+ * @param[in] peer remote peer
+ */
 #define TLS_RET_HANDSHAKE_RES(peer)                                                                \
 if (g_tlsHandshakeCallback)                                                                        \
 {                                                                                                  \
     CAErrorInfo_t errorInfo = {.result = CA_STATUS_FAILED};                                        \
     g_tlsHandshakeCallback(&peer->sep.endpoint, &errorInfo);                                       \
 }
-
-#define TLS_CHECK_HANDSHAKE_FAIL(peer, ret, str, mutex, error)                                     \
+/**@def TLS_CHECK_HANDSHAKE_FAIL(peer, ret, str, mutex, error, msg)
+ *
+ * Checks handshake result and send allert if needed.
+ *
+ * @param[in] peer remote peer
+ * @param[in] ret error code
+ * @param[in] str debug string
+ * @param[in] mutex ca mutex
+ * @param[in] return error code
+ * @param[in] msg allert message
+ */
+#define TLS_CHECK_HANDSHAKE_FAIL(peer, ret, str, mutex, error, msg)                                \
 if (0 != ret && MBEDTLS_ERR_SSL_WANT_READ != ret &&  MBEDTLS_ERR_SSL_WANT_WRITE != ret)            \
 {                                                                                                  \
     OIC_LOG_V(ERROR, NET_TLS_TAG, "%s: -0x%x", str, -ret);                                         \
-    TLS_CLOSE_NOTIFY(peer, ret);                                                                   \
+    if ((int) MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE != (int) ret &&                                  \
+        (int) MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY != (int) ret &&                                    \
+        (int) MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO != (int) ret)                                    \
+    {                                                                                              \
+        mbedtls_ssl_send_alert_message(&peer->ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, msg);            \
+    }                                                                                              \
     TLS_RET_HANDSHAKE_RES(peer);                                                                   \
     removePeerFromList(&peer->sep.endpoint);                                                       \
     if (mutex)                                                                                     \
     {                                                                                              \
         ca_mutex_unlock(g_tlsContextMutex);                                                        \
     }                                                                                              \
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);                                             \
     return error;                                                                                  \
 }
 
@@ -159,14 +189,58 @@ int tlsCipher[ADAPTER_CIPHER_MAX][2] =
     {MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 0}
 };
 
+static int g_cipherSuitesList[2 + 1];
+
 mbedtls_ecp_group_id curve[ADAPTER_CURVE_MAX][2] =
 {
     {MBEDTLS_ECP_DP_SECP256R1, 0}
 };
 
-//TODO add description
 static PkiInfo_t g_pkiInfo = {{NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}};
 
+typedef struct  {
+    int code;
+    int alert;
+} CrtVerifyAlert_t;
+
+static const CrtVerifyAlert_t crtVerifyAlerts[] = {
+    {MBEDTLS_X509_BADCERT_EXPIRED,       MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED},
+    {MBEDTLS_X509_BADCERT_REVOKED,       MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED},
+    {MBEDTLS_X509_BADCERT_CN_MISMATCH,   MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN},
+    {MBEDTLS_X509_BADCERT_NOT_TRUSTED,   MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA},
+    {MBEDTLS_X509_BADCRL_NOT_TRUSTED,    MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA},
+    {MBEDTLS_X509_BADCRL_EXPIRED,        MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY},
+    {MBEDTLS_X509_BADCERT_MISSING,       MBEDTLS_SSL_ALERT_MSG_NO_CERT},
+    {MBEDTLS_X509_BADCERT_SKIP_VERIFY,   MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY},
+    {MBEDTLS_X509_BADCERT_OTHER,         MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR},
+    {MBEDTLS_X509_BADCERT_FUTURE,        MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCRL_FUTURE,         MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY},
+    {MBEDTLS_X509_BADCERT_KEY_USAGE,     MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCERT_NS_CERT_TYPE,  MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCERT_BAD_MD,        MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCERT_BAD_PK,        MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCERT_BAD_KEY,       MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCRL_BAD_MD,         MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCRL_BAD_PK,         MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {MBEDTLS_X509_BADCRL_BAD_KEY,        MBEDTLS_SSL_ALERT_MSG_BAD_CERT},
+    {0, 0}
+};
+
+static int getAlertCode(uint32_t flags)
+{
+    const CrtVerifyAlert_t *cur;
+
+    for (cur = crtVerifyAlerts; cur->alert != 0 ; cur++)
+    {
+        if (flags & cur->code)
+        {
+            return cur->alert;
+        }
+    }
+    return 0;
+}
+
 #ifndef NDEBUG
 /**
  * Pass a message to the OIC logger.
@@ -220,6 +294,8 @@ typedef struct TlsContext
     AdapterCipher_t cipher;
     TlsCallbacks_t adapterCallbacks[MAX_SUPPORTED_ADAPTERS];
     mbedtls_x509_crl crl;
+    bool cipherFlag[2];
+    int selectedCipher;
 
 } TlsContext_t;
 
@@ -234,7 +310,11 @@ static TlsContext_t * g_caTlsContext = NULL;
  * @brief callback to get TLS credentials (same as for DTLS)
  */
 static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
-
+/**
+ * @var g_getCerdentilTypesCallback
+ * @brief callback to get different credential types from SRM
+ */
+static CAgetCredentialTypesHandler g_getCredentialTypesCallback = NULL;
 /**
  * @var g_getPkixInfoCallback
  *
@@ -255,7 +335,7 @@ static ca_mutex g_tlsContextMutex = NULL;
 static CAErrorCallback g_tlsHandshakeCallback = NULL;
 
 /**
- * Data structure for holding the data to be rceived.
+ * Data structure for holding the data to be received.
  */
 typedef struct TlsRecBuf
 {
@@ -291,6 +371,12 @@ void CAsetPkixInfoCallback(CAgetPkixInfoHandler infoCallback)
     g_getPkixInfoCallback = infoCallback;
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
 }
+void CAsetCredentialTypesCallback(CAgetCredentialTypesHandler credTypesCallback)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    g_getCredentialTypesCallback = credTypesCallback;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
 /**
  * Write callback.
  *
@@ -334,7 +420,6 @@ static int recvTls(void * tep, unsigned char * data, size_t dataLen)
     memcpy(data, recBuf->buff + recBuf->loaded, retLen);
     recBuf->loaded += retLen;
 
-    OIC_LOG_BUFFER(DEBUG, NET_TLS_TAG, data, retLen);
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
     return (int)retLen;
 }
@@ -405,64 +490,67 @@ static int parseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buf
     }
     return 0;
 }
-//TODO add description
+//Loads PKIX related information from SRM
 static int loadX509()
 {
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(g_getPkixInfoCallback, NET_TLS_TAG, "PKIX info callback is NULL", -1);
-
+    bool loadOwnCred = true;
     g_getPkixInfoCallback(&g_pkiInfo);
 
-    int ret = parseChain(&g_caTlsContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len);
-    if(0 != ret)
+    // optional
+    int ret = parseChain(&g_caTlsContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len);
+    if (0 != ret)
     {
-        OIC_LOG(ERROR, NET_TLS_TAG, "CA chain parsing error");
-        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
-        return -1;
+        OIC_LOG(WARNING, NET_TLS_TAG, "Own certificate chain parsing error");
+        goto required;
     }
-    ret = parseChain(&g_caTlsContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len);
-    if(0 != ret)
+    ret =  mbedtls_pk_parse_key(&g_caTlsContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
+                                                                               NULL, 0);
+    if (0 != ret)
     {
-        OIC_LOG(ERROR, NET_TLS_TAG, "Own certificate chain parsing error");
-        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
-        return -1;
+        OIC_LOG(WARNING, NET_TLS_TAG, "Key parsing error");
+        goto required;
     }
 
-    ret =  mbedtls_pk_parse_key(&g_caTlsContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
-                                                                                           NULL, 0);
-    if(0 != ret)
+    ret = mbedtls_ssl_conf_own_cert(&g_caTlsContext->serverConf, &g_caTlsContext->crt,
+                                                                 &g_caTlsContext->pkey);
+    if (0 != ret)
     {
-        OIC_LOG(ERROR, NET_TLS_TAG, "Key parsing error");
-        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
-        return -1;
+        OIC_LOG(WARNING, NET_TLS_TAG, "Own certificate parsing error");
+        goto required;
     }
-    ret = mbedtls_x509_crl_parse_der(&g_caTlsContext->crl, g_pkiInfo.crl.data, g_pkiInfo.crl.len);
+    ret = mbedtls_ssl_conf_own_cert( &g_caTlsContext->clientConf, &g_caTlsContext->crt,
+                                                                  &g_caTlsContext->pkey);
     if(0 != ret)
     {
-        OIC_LOG(ERROR, NET_TLS_TAG, "CRL parsing error");
-        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
-        //TODO
-        //return -1;
+        OIC_LOG(WARNING, NET_TLS_TAG, "Own certificate configuration error");
+        goto required;
     }
 
-    mbedtls_ssl_conf_ca_chain(&g_caTlsContext->clientConf, &g_caTlsContext->ca, NULL);
-    mbedtls_ssl_conf_ca_chain(&g_caTlsContext->serverConf, &g_caTlsContext->ca, NULL);
+    required:
 
-    ret = mbedtls_ssl_conf_own_cert(&g_caTlsContext->serverConf, &g_caTlsContext->crt,
-                                                                             &g_caTlsContext->pkey);
+    ret = parseChain(&g_caTlsContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len);
     if(0 != ret)
     {
-        OIC_LOG(ERROR, NET_TLS_TAG, "Certificate parsing error");
+        OIC_LOG(ERROR, NET_TLS_TAG, "CA chain parsing error");
         OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
         return -1;
     }
-    ret = mbedtls_ssl_conf_own_cert( &g_caTlsContext->clientConf, &g_caTlsContext->crt,
-                                                                             &g_caTlsContext->pkey);
+
+    ret = mbedtls_x509_crl_parse_der(&g_caTlsContext->crl, g_pkiInfo.crl.data, g_pkiInfo.crl.len);
     if(0 != ret)
     {
-        OIC_LOG(ERROR, NET_TLS_TAG, "Certificate parsing error");
-        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
-        return -1;
+        OIC_LOG(WARNING, NET_TLS_TAG, "CRL parsing error");
+        mbedtls_ssl_conf_ca_chain(&g_caTlsContext->clientConf, &g_caTlsContext->ca, NULL);
+        mbedtls_ssl_conf_ca_chain(&g_caTlsContext->serverConf, &g_caTlsContext->ca, NULL);
+    }
+    else
+    {
+        mbedtls_ssl_conf_ca_chain(&g_caTlsContext->clientConf, &g_caTlsContext->ca,
+                                                                              &g_caTlsContext->crl);
+        mbedtls_ssl_conf_ca_chain(&g_caTlsContext->serverConf, &g_caTlsContext->ca,
+                                                                              &g_caTlsContext->crl);
     }
 
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
@@ -730,20 +818,69 @@ static TlsEndPoint_t * newTlsEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl
 static int initPskIdentity(mbedtls_ssl_config * config)
 {
     uint8_t idBuf[UUID_LENGTH] = {0};
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(config, NET_TLS_TAG, "Param config is NULL" , -1);
 
     if (0 > g_getCredentialsCallback(CA_DTLS_PSK_IDENTITY, NULL, 0, idBuf, UUID_LENGTH))
     {
         OIC_LOG(ERROR, NET_TLS_TAG, "Identity not found");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
         return -1;
     }
     if (0 != mbedtls_ssl_conf_psk(config, idBuf, 0, idBuf, UUID_LENGTH))
     {
         OIC_LOG(ERROR, NET_TLS_TAG, "Identity initialization failed!");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
         return -1;
     }
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
     return 0;
 }
+static void setupCipher(mbedtls_ssl_config * config)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    if (NULL == g_getCredentialTypesCallback)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Param callback is null");
+        return;
+    }
+
+    g_getCredentialTypesCallback(g_caTlsContext->cipherFlag);
+    // Retrieve the PSK credential from SRM
+    // PIN OTM if (true == g_caTlsContext->cipherFlag[0] && 0 != initPskIdentity(config))
+    if (0 != initPskIdentity(config))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "PSK identity initialization failed!");
+    }
+
+    // Retrieve the ECC credential from SRM
+    if (true == g_caTlsContext->cipherFlag[1] || ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA == g_caTlsContext->cipher)
+    {
+        int ret = loadX509();
+        if (0 != ret)
+        {
+            OIC_LOG(ERROR, NET_TLS_TAG, "Failed to init X.509");
+        }
+    }
+    if (ADAPTER_CIPHER_MAX == g_caTlsContext->cipher)
+    {
+        int index = 0;
+        memset(g_cipherSuitesList, 0, sizeof(g_cipherSuitesList));
+        if (true == g_caTlsContext->cipherFlag[1])
+        {
+            g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
+            index ++;
+        }
+        if (true == g_caTlsContext->cipherFlag[0])
+        {
+           g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+        }
+
+        mbedtls_ssl_conf_ciphersuites(config, g_cipherSuitesList);
+    }
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
 /**
  * Initiate TLS handshake with endpoint.
  *
@@ -759,13 +896,7 @@ static TlsEndPoint_t * initiateTlsHandshake(const CAEndpoint_t *endpoint)
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(endpoint, NET_TLS_TAG, "Param endpoint is NULL" , NULL);
 
-    // Retrieve the credentials blob from security module
-    if (ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 == g_caTlsContext->cipher &&
-            0 != initPskIdentity(&g_caTlsContext->clientConf))
-    {
-        OIC_LOG(ERROR, NET_TLS_TAG, "Client PSK identity initialization failed!");
-        return NULL;
-    }
+
 
     tep = newTlsEndPoint(endpoint, &g_caTlsContext->clientConf);
     if (NULL == tep)
@@ -774,17 +905,8 @@ static TlsEndPoint_t * initiateTlsHandshake(const CAEndpoint_t *endpoint)
         return NULL;
     }
 
-    if (ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caTlsContext->cipher ||
-        ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA == g_caTlsContext->cipher)
-    {
-        ret = loadX509();
-        if (0 != ret)
-        {
-            OIC_LOG(ERROR, NET_TLS_TAG, "Failed to init X.509");
-            deleteTlsEndPoint(tep);
-            return NULL;
-        }
-    }
+    //Load allowed SVR suites from SVR DB
+    setupCipher(&g_caTlsContext->clientConf);
 
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "Add %s:%d", tep->sep.endpoint.addr, tep->sep.endpoint.port);
     ret = u_arraylist_add(g_caTlsContext->peerList, (void *) tep);
@@ -802,7 +924,7 @@ static TlsEndPoint_t * initiateTlsHandshake(const CAEndpoint_t *endpoint)
         {
             break;
         }
-        TLS_CHECK_HANDSHAKE_FAIL(tep, ret, "Handshake error", 0, NULL);
+        TLS_CHECK_HANDSHAKE_FAIL(tep, ret, "Handshake error", 0, NULL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
     }
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
     return tep;
@@ -985,8 +1107,8 @@ CAResult_t CAinitTlsAdapter()
     mbedtls_debug_set_threshold(MBED_TLS_DEBUG_LEVEL);
 #endif
 
-    // set default cipher to PSK
-    CAsetTlsCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256);
+    // set default cipher
+    g_caTlsContext->cipher = ADAPTER_CIPHER_MAX;
 
     // init X.509
     mbedtls_x509_crt_init(&g_caTlsContext->ca);
@@ -1235,12 +1357,6 @@ CAResult_t CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
         return CA_STATUS_FAILED;
     }
 
-    if (ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 == g_caTlsContext->cipher &&
-            0 != initPskIdentity(&g_caTlsContext->serverConf))
-    {
-        ca_mutex_unlock(g_tlsContextMutex);
-        return CA_STATUS_FAILED;
-    }
 
     TlsEndPoint_t * peer = getTlsPeer(&sep->endpoint);
     if (NULL == peer)
@@ -1252,19 +1368,8 @@ CAResult_t CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
             ca_mutex_unlock(g_tlsContextMutex);
             return CA_STATUS_FAILED;
         }
-
-        if (ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caTlsContext->cipher ||
-            ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA == g_caTlsContext->cipher)
-        {
-            ret = loadX509();
-            if (0 != ret)
-            {
-                OIC_LOG(ERROR, NET_TLS_TAG, "Failed to init X.509");
-                deleteTlsEndPoint(peer);
-                ca_mutex_unlock(g_tlsContextMutex);
-                return CA_STATUS_FAILED;
-            }
-        }
+        //Load allowed SVR suites from SVR DB
+        setupCipher(&g_caTlsContext->serverConf);
 
         ret = u_arraylist_add(g_caTlsContext->peerList, (void *) peer);
         if (!ret)
@@ -1275,7 +1380,7 @@ CAResult_t CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
             return CA_STATUS_FAILED;
         }
     }
-    OIC_LOG_BUFFER(DEBUG, NET_TLS_TAG, data, dataLen);
+
     peer->recBuf.buff = data;
     peer->recBuf.len = dataLen;
     peer->recBuf.loaded = 0;
@@ -1289,10 +1394,18 @@ CAResult_t CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
         {
             break;
         }
-        TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Handshake error", 1, CA_STATUS_FAILED);
+        uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
+        if (0 != flags)
+        {
+            OIC_LOG_BUFFER(ERROR, NET_TLS_TAG, &flags, sizeof(flags));
+            TLS_CHECK_HANDSHAKE_FAIL(peer, flags, "Cert verification failed", 1,
+                                                     CA_STATUS_FAILED, getAlertCode(flags));
+        }
+        TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Handshake error", 1, CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
         if (MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC == peer->ssl.state)
         {
             memcpy(peer->master, peer->ssl.session_negotiate->master, sizeof(peer->master));
+            g_caTlsContext->selectedCipher = peer->ssl.session_negotiate->ciphersuite;
         }
 
         if (MBEDTLS_SSL_HANDSHAKE_OVER == peer->ssl.state)
@@ -1308,29 +1421,26 @@ CAResult_t CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
             }
             else
             {
-                if (ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caTlsContext->cipher)
+                if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caTlsContext->selectedCipher)
                 {
                     char uuid[UUID_LENGTH * 2 + 5] = {0};
                     void * uuidPos = NULL;
                     void * userIdPos = NULL;
                     const mbedtls_x509_crt * peerCert = mbedtls_ssl_get_peer_cert(&peer->ssl);
                     ret = (NULL == peerCert ? -1 : 0);
-                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve subject",
-                                                                               1, CA_STATUS_FAILED);
-                    ret = mbedtls_ssl_get_verify_result(&peer->ssl);
-                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve subject",
-                                                                               1, CA_STATUS_FAILED);
+                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve cert", 1,
+                                                CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_NO_CERT);
                     uuidPos = memmem((void *) peerCert->subject_raw.p, peerCert->subject_raw.len,
                                                      (void *) UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
 
                     ret = (NULL == uuidPos ? -1 : 0);
-                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve subject",
-                                                                               1, CA_STATUS_FAILED);
+                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve subject", 1,
+                                        CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
 
                     memcpy(uuid, uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
                     ret = ConvertStrToUuid(uuid, &peer->sep.identity);
-                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to convert subject",
-                                                                               1, CA_STATUS_FAILED);
+                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to convert subject", 1,
+                                        CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
 
                     userIdPos = memmem((void *) peerCert->subject_raw.p, peerCert->subject_raw.len,
                                                  (void *) USERID_PREFIX, sizeof(USERID_PREFIX) - 1);
@@ -1338,12 +1448,12 @@ CAResult_t CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
                     {
                         memcpy(uuid, userIdPos + sizeof(USERID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
                         ret = ConvertStrToUuid(uuid, &peer->sep.userId);
-                        TLS_CHECK_HANDSHAKE_FAIL(peer, ret,
-                                 "Failed to convert subject alternative name", 1, CA_STATUS_FAILED);
+                        TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to convert subject alt name", 1,
+                                          CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
                     }
                     else
                     {
-                        OIC_LOG(DEBUG, NET_TLS_TAG, "Subject alternative name not found");
+                        OIC_LOG(WARNING, NET_TLS_TAG, "Subject alternative name not found");
                     }
                 }
             }
@@ -1418,10 +1528,13 @@ void CAsetTlsAdapterCallbacks(CAPacketReceivedCallback recvCallback,
 CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
 {
     OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(g_getCredentialTypesCallback, NET_TLS_TAG, "Param callback is null", CA_STATUS_FAILED);
+    g_getCredentialTypesCallback(g_caTlsContext->cipherFlag);
     switch(cipher)
     {
         case MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA:
         {
+            //todo check that Cred with RSA cert exists
             mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->clientConf,
                                          tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
             mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->serverConf,
@@ -1431,6 +1544,11 @@ CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
         }
         case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
         {
+            if (false == g_caTlsContext->cipherFlag[1])
+            {
+                OIC_LOG(ERROR, NET_TLS_TAG, "No Credential for ECC");
+                return CA_STATUS_FAILED;
+            }
             mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->clientConf,
                                          tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
             mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->serverConf,
@@ -1449,6 +1567,13 @@ CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
         }
         case MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
         {
+#if 0 // PIN OTM
+            if (false == g_caTlsContext->cipherFlag[0])
+            {
+                OIC_LOG(ERROR, NET_TLS_TAG, "No Credential for PSK");
+                return CA_STATUS_FAILED;
+            }
+#endif
             mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->clientConf,
                                           tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
             mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->serverConf,
index 18f3509..a287608 100644 (file)
@@ -65,6 +65,7 @@ extern void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback);
 #ifdef __WITH_TLS__
 extern void CAsetPkixInfoCallback(CAgetPkixInfoHandler infCallback);
 extern void CAsetTlsCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback);
+extern void CAsetCredentialTypesCallback(CAgetCredentialTypesHandler credCallback);
 #endif
 
 
@@ -222,6 +223,19 @@ CAResult_t CAregisterPkixInfoHandler(CAgetPkixInfoHandler getPkixInfoHandler)
     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
     return CA_STATUS_OK;
 }
+
+CAResult_t CAregisterGetCredentialTypesHandler(CAgetCredentialTypesHandler getCredTypesHandler)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+    if (!g_isInitialized)
+    {
+        return CA_STATUS_NOT_INITIALIZED;
+    }
+    CAsetCredentialTypesCallback(getCredTypesHandler);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
 #endif
 
 #ifdef __WITH_X509__
index 2d9e173..e7429ff 100644 (file)
@@ -120,8 +120,7 @@ if target_os in ['windows', 'msys_nt']:
        libocsrm_src  = libocsrm_src + [OCSRM_SRC + 'strptime.c']
 
 if (env.get('DTLS_WITH_X509') == '1' or env.get('WITH_TCP') == True) and env.get('SECURED') == '1':
-       crl_src = [OCSRM_SRC + 'crlresource.c']
-       libocsrm_src  = libocsrm_src + crl_src
+       libocsrm_src  = libocsrm_src + [OCSRM_SRC + 'crlresource.c', OCSRM_SRC + 'pkix_interface.c']
 
 libocsrm_conf = Configure(libocsrm_env)
 if libocsrm_conf.CheckFunc('strptime'):
index 7daf51f..3596377 100644 (file)
@@ -101,6 +101,14 @@ OicSecAce_t* DuplicateACE(const OicSecAce_t* ace);
 OCStackResult InstallNewACL(const uint8_t* payload, const size_t size);
 
 /**
+ * This function installs a new ACL.
+ *
+ * @param acl  new acl to install.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InstallNewACL2(const OicSecAcl_t* acl);
+/**
  * This function updates default ACE which is required for ownership transfer.
  * This function should be invoked after OTM is complete to prevent anonymous user access.
  *
@@ -126,6 +134,16 @@ OCStackResult SetAclRownerId(const OicUuid_t* newROwner);
  */
 OCStackResult GetAclRownerId(OicUuid_t *rowneruuid);
 
+/**
+ * This function converts CBOR data into ACL.
+ *
+ * @param cborPayload is the pointer to cbor payload to parse.
+ * @param size of the cbor payload.
+ *
+ * @return ::acl instance of @ref OicSecAcl_t structure or NULL if error occurs
+ */
+OicSecAcl_t* CBORPayloadToAcl2(const uint8_t *cborPayload, const size_t size);
+
 #ifdef __cplusplus
 }
 #endif
index d3161ad..beab0c4 100644 (file)
@@ -190,12 +190,30 @@ OCStackResult GetCredRownerId(OicUuid_t *rowneruuid);
 
 #ifdef __WITH_TLS__
 /**
- * @def CA_SUBJECT_ID
- * @brief subject uuid for credential with CA certificates
+ * Used by mbedTLS to retrieve trusted CA certificates
+ *
+ * @param[out] crt certificates to be filled.
  */
-#define CA_SUBJECT_ID ("00000000-0000-0000-0000-000000000000")
-void GetPkixInfo(PkiInfo_t * inf);
-#endif
+void GetDerCaCert(ByteArray * crt);
+/**
+ * Used by mbedTLS to retrieve own certificate chain
+ *
+ * @param[out] crt certificate chain to be filled.
+ */
+void GetDerOwnCert(ByteArray * crt);
+/**
+ * Used by mbedTLS to retrieve owm private key
+ *
+ * @param[out] key key to be filled.
+ */
+void GetDerKey(ByteArray * key);
+/**
+ * Used by CA to retrieve credential types
+ *
+ * @param[out] key key to be filled.
+ */
+void InitCipherSuiteList(bool *list);
+#endif // __WITH_TLS__
 #ifdef __cplusplus
 }
 #endif
index 3e98f8c..a2f135c 100644 (file)
@@ -21,8 +21,7 @@
 #ifndef IOTVT_SRM_CRLR_H
 #define IOTVT_SRM_CRLR_H
 
-#include "octypes.h"
-#include "securevirtualresourcetypes.h"
+#include "ocpayload.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,7 +34,7 @@ extern "C" {
  *
  * @return ::OC_STACK_OK for Success, otherwise some error value.
  */
-OCStackResult UpdateCRLResource(const OicSecCrl_t *crl);
+OCStackResult UpdateCRLResource(OicSecCrl_t *crl);
 
 /**
  * This function get encoded with base64 CRL from SRM.
@@ -60,12 +59,14 @@ void  GetDerCrl(ByteArray* crlArray);
  * will be allocated by the function and content of *crl will be ignored.
  * @param payload is the converted cbor value.
  * @param size is a pointer to length of the CRL buffer. Should be not NULL.
+ * @param lastUpdate optional field contains CRL last update time
  *
  * @note Caller responsible for crl buffer memory (use OICFree to free it).
  *
  * @return ::OC_STACK_OK if success, otherwise some error value.
  */
-OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size);
+OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size,
+                               char *lastUpdate);
 
 /**
  * This function converts CBOR to CRL
@@ -102,6 +103,23 @@ OCStackResult DeInitCRLResource();
  */
 OicSecCrl_t *GetCRLResource();
 
+/**
+ * This function frees resources inside given OicSecCrl_t object
+ *
+ * @param crl  crl object
+ */
+void DeleteCrl(OicSecCrl_t *crl);
+
+/**
+ * This function gets time when CRL was last updated in database
+ * Function allocates memory for lastUpdate and
+ * Caller is responsible to free that memory
+ *
+ * @param lastUpdate    pointer to last update string.
+ * @return ::OC_STACK_OK for Success, otherwise some error value.
+ */
+OCStackResult getLastUpdateFromDB(char **lastUpdate);
+
 #ifdef __cplusplus
 }
 #endif
index f7f0773..ba7bcf6 100644 (file)
@@ -153,6 +153,7 @@ extern const char * OIC_JSON_SEC_V_NAME;
 extern const char * OIC_JSON_EMPTY_STRING;
 
 extern const char * TRUST_CA;
+extern const char * PRIMARY_CERT;
 
 extern OicUuid_t WILDCARD_SUBJECT_ID;
 extern OicUuid_t WILDCARD_SUBJECT_B64_ID;
diff --git a/resource/csdk/security/include/pkix_interface.h b/resource/csdk/security/include/pkix_interface.h
new file mode 100644 (file)
index 0000000..e4e5835
--- /dev/null
@@ -0,0 +1,40 @@
+/******************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#ifndef PKIX_INTERFACE_H
+#define PKIX_INTERFACE_H
+
+#include "cainterface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * This method is used by mbedTLS/SRM to retrieve PKIX related info
+ *
+ * @param[out] inf structure with certificate, private key and crl to be filled.
+ *
+ */
+void GetPkixInfo(PkiInfo_t * inf);
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PKIX_INTERFACE_H
index 77af258..2101381 100644 (file)
@@ -495,7 +495,7 @@ struct OicSecCrl
 {
     uint16_t CrlId;
     ByteArray ThisUpdate;
-    ByteArray CrlData;
+    OicSecKey_t CrlData;
 };
 #endif /* __WITH_X509__ or __WITH_TLS__ */
 
index 84bae32..4ef15ed 100644 (file)
@@ -36,6 +36,7 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../../c_common/oic_malloc/include',
                'include',
                'include/internal',
+               'include/cloud',
                'include/oxm',
                '../../resource/csdk/security/include',
                '../../../../extlibs/cjson/',
@@ -67,6 +68,9 @@ provisioning_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'connecti
 
 provisioning_env.AppendUnique(LIBS = ['tinydtls'])
 
+if provisioning_env.get('WITH_TCP') == True:
+       provisioning_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
+
 if provisioning_env.get('DTLS_WITH_X509') == '1':
        provisioning_env.AppendUnique(LIBS = ['CKManager', 'asn1'])
 if provisioning_env.get('WITH_TCP') == True:
@@ -104,6 +108,15 @@ provisioning_src = [
        'src/oxmrandompin.c',
        'src/provisioningdatabasemanager.c' ]
 
+if provisioning_env.get('WITH_TCP') == True:
+       provisioning_src = provisioning_src + [
+       'src/cloud/utils.c',
+       'src/cloud/crl.c',
+       'src/cloud/aclgroup.c',
+       'src/cloud/aclinvite.c',
+       'src/cloud/aclid.c',
+       'src/cloud/csr.c']
+
 if target_os not in ['tizen', 'windows', 'msys_nt']:
        provisioning_src = provisioning_src + [root_dir+'/extlibs/sqlite3/sqlite3.c' ]
 
diff --git a/resource/csdk/security/provisioning/include/cloud/occloudprovisioning.h b/resource/csdk/security/provisioning/include/cloud/occloudprovisioning.h
new file mode 100644 (file)
index 0000000..9b3f9b1
--- /dev/null
@@ -0,0 +1,406 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#ifndef OC_CLOUD_PROVISIONING_H
+#define OC_CLOUD_PROVISIONING_H
+
+#include "octypes.h"
+#include "securevirtualresourcetypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef void (*OCCloudResponseCB )(void* ctx, OCStackResult result, void* data);
+
+typedef struct cloudAce cloudAce_t;
+
+struct cloudAce {
+    char *aceId;
+    OicUuid_t subjectuuid;
+    uint16_t stype;
+    uint16_t permission;
+    OicSecRsrc_t *resources;
+    OicSecValidity_t *validities;
+    cloudAce_t *next;
+};
+
+typedef struct {
+    char **array;
+    size_t length;
+}stringArray_t;
+
+typedef struct {
+    stringArray_t gidlist;
+    stringArray_t midlist;
+}stringArrayPair_t;
+
+typedef struct {
+    stringArrayPair_t invite;
+    stringArrayPair_t invited;
+}inviteResponse_t;
+
+/**
+ * Certificate-Issue request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudCertificateIssueRequest(void* ctx,
+                                             const OCDevAddr *endPoint,
+                                             OCCloudResponseCB callback);
+
+/**
+ * CRL GET request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudGetCRL(void* ctx,
+                            const OCDevAddr *endPoint,
+                            OCCloudResponseCB callback);
+
+/**
+ * CRL POST request function (with Serial Numbers list to revoke)
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] thisUpdate        mandatory parameter thisUpdate
+ * @param[in] nextUpdate        mandatory parameter nextUpdate
+ * @param[in] crl               optional parameter crl
+ * @param[in] serialNumbers     optional parameter serial numbers
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudPostCRL(void* ctx,
+                             const char *thisUpdate,
+                             const char *nextUpdate,
+                             const OCByteString *crl,
+                             const stringArray_t *serialNumbers,
+                             const OCDevAddr *endPoint,
+                             OCCloudResponseCB callback);
+
+/**
+ * ACL id retrieve by device id
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] deviceId          mandatory parameter device id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclIdGetByDevice(void* ctx,
+                                      const char *deviceId,
+                                      const OCDevAddr *endPoint,
+                                      OCCloudResponseCB callback);
+
+/**
+ * ACL id create
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] ownerId           mandatory parameter owner id
+ * @param[in] deviceId          mandatory parameter device id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclIdCreate(void* ctx,
+                                 const char *ownerId,
+                                 const char *deviceId,
+                                 const OCDevAddr *endPoint,
+                                 OCCloudResponseCB callback);
+
+/**
+ * ACL id delete
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] aclId             mandatory parameter acl id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclIdDelete(void* ctx,
+                                 const char *aclId,
+                                 const OCDevAddr *endPoint,
+                                 OCCloudResponseCB callback);
+
+/**
+ * ACL individual get info
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] aclId             mandatory parameter acl id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclIndividualGetInfo(void* ctx,
+                                          const char *aclId,
+                                          const OCDevAddr *endPoint,
+                                          OCCloudResponseCB callback);
+
+/**
+ * ACL individual update ACE
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] aclId             mandatory parameter acl id
+ * @param[in] aces              mandatory parameter aces
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclIndividualUpdateAce(void* ctx,
+                                            const char *aclId,
+                                            const cloudAce_t *aces,
+                                            const OCDevAddr *endPoint,
+                                            OCCloudResponseCB callback);
+
+/**
+ * ACL individual delete
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] aclId             mandatory parameter acl id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclIndividualDelete(void* ctx,
+                                         const char *aclId,
+                                         const OCDevAddr *endPoint,
+                                         OCCloudResponseCB callback);
+
+/**
+ * ACL post group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] groupType         mandatory parameter group type
+ * @param[in] groupMasterId     optional parameter group master id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclCreateGroup(void* ctx,
+                                    const char *groupType,
+                                    const char *groupMasterId,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback);
+
+/**
+ * ACL get group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] memberId          mandatory parameter member id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclFindMyGroup(void* ctx,
+                                    const char *memberId,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback);
+
+/**
+ * ACL delete group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] groupMasterId     optional parameter group master id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclDeleteGroup(void* ctx,
+                                    const char *groupId,
+                                    const char *groupMasterId,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback);
+
+/**
+ * ACL join to invited group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclJoinToInvitedGroup(void* ctx,
+                                           const char *groupId,
+                                           const OCDevAddr *endPoint,
+                                           OCCloudResponseCB callback);
+
+/**
+ * ACL observe group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclObserveGroup(void* ctx,
+                                     const char *groupId,
+                                     const OCDevAddr *endPoint,
+                                     OCCloudResponseCB callback);
+
+/**
+ * ACL share device into group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] memberIds         mandatory parameter members list
+ * @param[in] deviceIds         mandatory parameter devices list
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclShareDeviceIntoGroup(void* ctx,
+                                             const char *groupId,
+                                             const stringArray_t *memberIds,
+                                             const stringArray_t *deviceIds,
+                                             const OCDevAddr *endPoint,
+                                             OCCloudResponseCB callback);
+
+/**
+ * ACL delete device from group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] memberIds         mandatory parameter members list
+ * @param[in] deviceIds         mandatory parameter devices list
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclDeleteDeviceFromGroup(void* ctx,
+                                              const char *groupId,
+                                              const stringArray_t *memberIds,
+                                              const stringArray_t *deviceIds,
+                                              const OCDevAddr *endPoint,
+                                              OCCloudResponseCB callback);
+
+/**
+ * ACL get group info request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] memberId          optional parameter member id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclGroupGetInfo(void* ctx,
+                                     const char *groupId,
+                                     const char *memberId,
+                                     const OCDevAddr *endPoint,
+                                     OCCloudResponseCB callback);
+
+/**
+ * ACL invite user to group request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] userId            optional parameter user id
+ * @param[in] groupIds          mandatory parameter groups list
+ * @param[in] memberIds         mandatory parameter members list
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclInviteUser(void* ctx,
+                                   const char *userId,
+                                   const stringArray_t *groupIds,
+                                   const stringArray_t *memberIds,
+                                   const OCDevAddr *endPoint,
+                                   OCCloudResponseCB callback);
+
+/**
+ * ACL get invitation request function
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] userId            optional parameter user id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclGetInvitation(void* ctx,
+                                      const char *userId,
+                                      const OCDevAddr *endPoint,
+                                      OCCloudResponseCB callback);
+
+/**
+ * ACL delete invitation request function (by receiver)
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] userId            optional parameter user id
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclDeleteInvitation(void* ctx,
+                                         const char *userId,
+                                         const char *groupId,
+                                         const OCDevAddr *endPoint,
+                                         OCCloudResponseCB callback);
+
+/**
+ * ACL cancel invitation request function (by sender)
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] userId            optional parameter user id
+ * @param[in] groupId           mandatory parameter group id
+ * @param[in] memberId          mandatory parameter member id
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclCancelInvitation(void* ctx,
+                                         const char *userId,
+                                         const char *groupId,
+                                         const char *memberId,
+                                         const OCDevAddr *endPoint,
+                                         OCCloudResponseCB callback);
+
+/**
+ * ACL check that given request can be applied to resource
+ *
+ * @param[in] ctx               user-defined context
+ * @param[in] subjectId         mandatory parameter subject id
+ * @param[in] deviceId          mandatory parameter device id
+ * @param[in] method            mandatory parameter method
+ * @param[in] uri               mandatory parameter uri
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudAclPolicyCheck(void* ctx,
+                                    const char *subjectId,
+                                    const char *deviceId,
+                                    const char *method,
+                                    const char *uri,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif //OC_CLOUD_PROVISIONING_H
diff --git a/resource/csdk/security/provisioning/include/cloud/utils.h b/resource/csdk/security/provisioning/include/cloud/utils.h
new file mode 100644 (file)
index 0000000..f6b1c04
--- /dev/null
@@ -0,0 +1,64 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#ifndef CLOUD_UTILS_H
+#define CLOUD_UTILS_H
+
+#include "occloudprovisioning.h"
+
+extern char *DEFAULT_QUERY;
+extern char *DEFAULT_PREFIX;
+
+typedef OCStackResult (*UserFunctionCB)(void *params, void **data, OCClientResponse *clientResponse);
+
+/**
+ * This function sets required CoAP prefix depending on
+ * secure or non-secure connection
+ *
+ * @param[in] secure   secure flag
+ */
+void setCoapPrefix(bool secure);
+
+/**
+ * This hepler function fills OCCallbackData
+ *
+ * @param[in] cbData       cloud host and port
+ * @param[in] ctx          external context
+ * @param[in] cb           external callback
+ * @param[in] fn           internal function
+ * @param[in] params       params to internal function
+ */
+void fillCallbackData(OCCallbackData *cbData, void *ctx, OCCloudResponseCB cb,
+                                              UserFunctionCB fn, void *params);
+
+/**
+ * Get the device id from db
+ *
+ * @return  device id
+ */
+char *getDeviceId();
+
+/**
+ * Clear previously filled array of strings
+ *
+ * @param[out] list           array of strings structure to clear
+ */
+void clearStringArray(stringArray_t *list);
+
+#endif // CLOUD_UTILS_H
index 001339b..97b90f0 100644 (file)
@@ -104,6 +104,16 @@ OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint1
 OCStackResult SRPSaveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
                                         OicEncodingType_t encodingType,uint16_t *credId);
 
+/**
+ * function to save own certificate chain into Cred of SVR.
+ *
+ * @param[in] cert own certificate chain to be saved in Cred of SVR.
+ * @param[in] key own secret key to be saved in Cred of SVR.
+ * @param[out] credId CredId of saved trust certificate chain in Cred of SVR.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult SRPSaveOwnCertChain(OicSecCert_t * cert, OicSecKey_t * key, uint16_t *credId);
+
 #endif // __WITH_X509__ || __WITH_TLS__
 /**
  * API to send Direct-Pairing Configuration to a device.
index d3947b1..5d8c8a7 100755 (executable)
@@ -38,7 +38,9 @@ extern "C"
 #define COAP_QUERY "coap://%s:%d%s"
 
 #define COAP_TCP_PREFIX "coap+tcp://"
+#define COAP_TCP_QUERY "coap+tcp://%s:%d%s"
 #define COAPS_TCP_PREFIX "coaps+tcp://"
+#define COAPS_TCP_QUERY "coaps+tcp://%s:%d%s"
 
 /**
  * Discover owned/unowned devices in the specified endpoint.
index 731d45f..34b58d4 100644 (file)
@@ -34,10 +34,12 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../../logger/include',
                '../../../stack/include',
                '../../../security/include',
+               '../../../security/include/internal',
                '../../../security/provisioning/include/internal',
                '../../../../oc_logger/include',
                '../include',
                '../include/oxm',
+               '../include/cloud',
                '../../include',
                '../../../../../extlibs/tinydtls',
                '../../../../../extlibs/cjson',
@@ -46,7 +48,8 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../../connectivity/inc/pkix',
                '../../../connectivity/common/inc',
                '../../../connectivity/lib/libcoap-4.1.1',
-               '../../../connectivity/api'
+               '../../../connectivity/api',
+               'cloud'
                ])
 
 target_os = env.get('TARGET_OS')
@@ -91,11 +94,19 @@ if target_os == 'tizen':
 provisioningclient = provisioning_env.Program('provisioningclient', 'provisioningclient.c')
 sampleserver_justworks = provisioning_env.Program('sampleserver_justworks', 'sampleserver_justworks.cpp')
 sampleserver_randompin = provisioning_env.Program('sampleserver_randompin', 'sampleserver_randompin.cpp')
+if provisioning_env.get('WITH_TCP') == True:
+    cloudClient_src = [
+        'cloudClient.c',
+        'cloud/cloudAuth.c',
+        'cloud/cloudWrapper.c',
+        'cloud/cloudDiscovery.c']
+    cloudClient = provisioning_env.Program('cloudClient', cloudClient_src)
 
 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/'
 
+
 clientdat = provisioning_env.Install(sec_provisioning_build_dir,
                                         sec_provisioning_src_dir + 'oic_svr_db_client.dat')
 justworksdat = provisioning_env.Install(sec_provisioning_build_dir,
@@ -104,8 +115,14 @@ randompindat = provisioning_env.Install(sec_provisioning_build_dir,
                                     sec_provisioning_src_dir+ 'oic_svr_db_server_randompin.dat')
 randompin_with_emptyuuid_dat = provisioning_env.Install(sec_provisioning_build_dir,
                                     sec_provisioning_src_dir+ 'oic_svr_db_randompin_with_empty_deviceid.dat')
+if provisioning_env.get('WITH_TCP') == True:
+    clouddat = provisioning_env.Install(sec_provisioning_build_dir,
+                                        sec_provisioning_src_dir + 'cloud.dat')
+    rootcert = provisioning_env.Install(sec_provisioning_build_dir,
+                                        sec_provisioning_src_dir + 'rootca.crt')
+    Alias("cloud", [clouddat, rootcert, cloudClient])
+    provisioning_env.AppendTarget("cloud")
 
 Alias("samples", [provisioningclient, sampleserver_justworks, sampleserver_randompin, clientdat, justworksdat, randompindat, randompin_with_emptyuuid_dat])
-
 provisioning_env.AppendTarget('samples')
 
diff --git a/resource/csdk/security/provisioning/sample/cloud.dat b/resource/csdk/security/provisioning/sample/cloud.dat
new file mode 100644 (file)
index 0000000..d08f163
Binary files /dev/null and b/resource/csdk/security/provisioning/sample/cloud.dat differ
diff --git a/resource/csdk/security/provisioning/sample/cloud.json b/resource/csdk/security/provisioning/sample/cloud.json
new file mode 100644 (file)
index 0000000..3ab5914
--- /dev/null
@@ -0,0 +1,68 @@
+{
+    "acl": {
+        "aclist": {
+            "aces": [
+                {
+                    "subjectuuid": "*",
+                    "resources": [
+                        {
+                            "href": "/oic/res",
+                            "rel": "",
+                            "rt": ["oic.wk.res"],
+                            "if": ["oic.if.ll"]
+                        },{
+                            "href": "/oic/d",
+                            "rel": "",
+                            "rt": ["oic.wk.d"],
+                            "if": ["oic.if.baseline", "oic.if.r"]
+                        },{
+                            "href": "/oic/p",
+                            "rel": "",
+                            "rt": ["oic.wk.p"],
+                            "if": ["oic.if.baseline", "oic.if.r"]
+                        }
+                    ],
+                    "permission": 2
+                },
+                {
+                    "subjectuuid": "*",
+                    "resources": [
+                        {
+                            "href": "/oic/sec/doxm",
+                            "rel": "",
+                            "rt": ["oic.r.doxm"],
+                            "if": ["oic.if.baseline"]
+                        },
+                        {
+                            "href": "/oic/sec/pstat",
+                            "rel": "",
+                            "rt": ["oic.r.pstat"],
+                            "if": ["oic.if.baseline"]
+                        }
+                    ],
+                    "permission": 2
+                }
+            ]
+        },
+        "rowneruuid" : "61646D69-6E44-6576-6963-655575696430"
+    },
+    "pstat": {
+        "isop": true,
+        "cm": 0,
+        "tm": 0,
+        "om": 3,
+        "sm": 3,
+        "deviceuuid": "61646D69-6E44-6576-6963-655575696430",
+        "rowneruuid": "61646D69-6E44-6576-6963-655575696430"
+    },
+    "doxm": {
+        "oxms": [0],
+        "oxmsel": 0,
+        "sct": 1,
+        "owned": true,
+        "deviceuuid": "61646D69-6E44-6576-6963-655575696430",
+        "x.org.iotivity.dpc": false,
+        "devowneruuid": "61646D69-6E44-6576-6963-655575696430",
+        "rowneruuid": "61646D69-6E44-6576-6963-655575696430"
+    }
+}
diff --git a/resource/csdk/security/provisioning/sample/cloud/cloudAuth.c b/resource/csdk/security/provisioning/sample/cloud/cloudAuth.c
new file mode 100644 (file)
index 0000000..27fafbb
--- /dev/null
@@ -0,0 +1,443 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#include "octypes.h"
+#include "logger.h"
+#include "payload_logging.h"
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "psinterface.h"
+#include "securevirtualresourcetypes.h"
+#include "doxmresource.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "srmutility.h"
+#include "pmutility.h"
+#include "credresource.h"
+#include "payload_logging.h"
+
+#include "utils.h"
+#include "cloudAuth.h"
+#include "cloudCommon.h"
+
+#define TAG "cloudAuth"
+
+#define LOGIN_OK 4
+
+#define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
+
+typedef struct
+{
+    char *accesstoken;
+    char *refreshtoken;
+    char *tokentype;
+    long  expiresin;
+    char *uid;
+    char *redirecturi;
+    char *certificate;
+    char *sid;
+} sessionObject_t;
+
+static sessionObject_t sessionObject = {0,0,0,0,0,0,0,0};
+
+/**
+ * Session free function
+ *
+ * @return  OCStackResult application result
+ */
+static void SessionFree()
+{
+    if (sessionObject.accesstoken)  OICFree(sessionObject.accesstoken);
+    if (sessionObject.refreshtoken) OICFree(sessionObject.refreshtoken);
+    if (sessionObject.tokentype)    OICFree(sessionObject.tokentype);
+    if (sessionObject.uid)          OICFree(sessionObject.uid);
+    if (sessionObject.redirecturi)  OICFree(sessionObject.redirecturi);
+    if (sessionObject.certificate)  OICFree(sessionObject.certificate);
+    if (sessionObject.sid)          OICFree(sessionObject.sid);
+
+    memset(&sessionObject, 0, sizeof(sessionObject_t));
+}
+
+/**
+ * Session init function
+ *
+ * @param[in] sessionObject session data
+ * @return  OCStackResult application result
+ */
+static OCStackResult SessionInit()
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    SessionFree(sessionObject);
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+
+    return OC_STACK_OK;
+}
+
+/**
+ * Session parse payload
+ *
+ * @param[in] payload
+ * @param[in] sessionObject session data
+ * @return  OCStackResult application result
+ */
+static OCStackResult SessionParsePayload(OCRepPayload *payload)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    VERIFY_NON_NULL(TAG, payload, ERROR);
+
+    SessionInit();
+
+    if (!OCRepPayloadGetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
+                                   &sessionObject.accesstoken))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: accesstoken");
+    }
+    if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REFRESH_TOKEN,
+                                   &sessionObject.refreshtoken))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: refreshtoken");
+    }
+    if (!OCRepPayloadGetPropString(payload, OC_RSRVD_TOKEN_TYPE,
+                                   &sessionObject.tokentype))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: tokentype");
+    }
+    if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN,
+                                &(sessionObject.expiresin)))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: expiresin");
+    }
+    if (!OCRepPayloadGetPropString(payload, OC_RSRVD_USER_UUID,
+                                   &sessionObject.uid))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: uid");
+    }
+    if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REDIRECT_URI,
+                                   &sessionObject.redirecturi))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: redirecturi");
+    }
+    if (!OCRepPayloadGetPropString(payload, OC_RSRVD_CERTIFICATE,
+                                   &sessionObject.certificate))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: certificate");
+    }
+    if (!OCRepPayloadGetPropString(payload, OC_RSRVD_SUBJECT_ID,
+                                   &sessionObject.sid))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: sid");
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+exit:
+    return OC_STACK_OK;
+}
+
+/**
+ * Sends Sign Up request to cloud
+ *
+ * @param[in] ctx                    context
+ * @param[in] handle                 handle
+ * @param[in] response               response from peer
+ * @return  OCStackApplicationResult application result
+ */
+static OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
+                                                          OCDoHandle handle,
+                                                          OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+
+    if (!response)
+    {
+        OIC_LOG(ERROR, TAG, "Received NULL response!");
+        goto exit;
+    }
+
+    if (response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Payload received");
+        OIC_LOG_PAYLOAD(DEBUG, response->payload);
+    }
+
+    if (response->result != LOGIN_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "Login error: %d",response->result);
+    }
+    else
+    {
+        OIC_LOG(DEBUG, TAG, "Login successful");
+        SessionParsePayload((OCRepPayload*)response->payload);
+    }
+exit:
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult CloudSignUp(const OCDevAddr *endPoint,
+                          const char *authProvider,
+                          const char *authToken)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (!endPoint || !authProvider || !authToken)
+    {
+        OIC_LOG(ERROR, TAG, "Some of the input params are NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char *deviceId = getDeviceId();
+    if (!deviceId)
+    {
+        OIC_LOG(ERROR, TAG, "Can't get the device id");
+        return OC_STACK_ERROR;
+    }
+
+    snprintf(uri, MAX_URI_LENGTH, DEFAULT_QUERY,
+             endPoint->addr, endPoint->port, OC_RSRVD_ACCOUNT_URI);
+
+    OCCallbackData cbData;
+    memset(&cbData, 0, sizeof(OCCallbackData));
+    cbData.cb = handleCloudSignUpResponse;
+    cbData.cd = unlockMenu;
+
+    OCRepPayload *payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
+    OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, OICStrdup(authProvider));
+    OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHCODE, OICStrdup(authToken));
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+/**
+ * Sends Sign In request to cloud
+ *
+ * @param[in] ctx                    context
+ * @param[in] handle                 handle
+ * @param[in] response               response from peer
+ * @return  OCStackApplicationResult application result
+ */
+static OCStackApplicationResult handleCloudSignInResponse(void *ctx,
+                                                          OCDoHandle handle,
+                                                          OCClientResponse *response)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+
+    if (!response)
+    {
+        OIC_LOG(ERROR, TAG, "Received NULL response!");
+        goto exit;
+    }
+
+    if (response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Payload received");
+        OIC_LOG_PAYLOAD(DEBUG, response->payload);
+    }
+
+    if (response->result < 4 && response->payload)
+    {
+        OIC_LOG_V(ERROR, TAG, "Sign In error: result: %d, payload exist: %s",
+                  response->result, response->payload ? "yes" : "no");
+        goto exit;
+    }
+
+    if (!OCRepPayloadGetPropString((OCRepPayload*)response->payload, OC_RSRVD_USER_UUID,
+                                   &(sessionObject.uid)))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: uid");
+    }
+
+    if (!OCRepPayloadGetPropInt((OCRepPayload*)response->payload, OC_RSRVD_EXPIRES_IN,
+                                &(sessionObject.expiresin)))
+    {
+        OIC_LOG(ERROR, TAG, "Cann't get: expiresin");
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+
+exit:
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult CloudSignIn(const OCDevAddr  *endPoint)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (!endPoint)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: endPoint is NULL",__func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if (!sessionObject.uid)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: UID is missing. Please run Sign Up first",__func__);
+        return OC_STACK_ERROR;
+    }
+
+    if (!sessionObject.accesstoken)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: accesstoken is missing. Please run Sign Up first",__func__);
+        return OC_STACK_ERROR;
+    }
+
+    char *deviceId = getDeviceId();
+    if (!deviceId)
+    {
+        OIC_LOG(ERROR, TAG, "Can't get the device id");
+        return OC_STACK_ERROR;
+    }
+
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if (NULL == payload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, sessionObject.uid);
+    OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
+    OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
+                              sessionObject.accesstoken);
+    OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, true);
+
+    char uri[MAX_URI_QUERY] = { 0, };
+    snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
+             endPoint->addr, endPoint->port,
+             OC_RSRVD_ACCOUNT_SESSION_URI);
+
+    OCCallbackData cbData;
+    memset(&cbData, 0, sizeof(OCCallbackData));
+    cbData.cb = handleCloudSignInResponse;
+    cbData.cd = unlockMenu;
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL,
+                       (OCPayload *)payload,
+                       CT_ADAPTER_TCP,
+                       OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+static OCStackApplicationResult handleCloudSignOutResponse(void *ctx,
+                                                           OCDoHandle handle,
+                                                           OCClientResponse *response)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+
+    if (!response)
+    {
+        OIC_LOG(ERROR, TAG, "Received NULL response!");
+        goto exit;
+    }
+
+    if (response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Payload received");
+        OIC_LOG_PAYLOAD(DEBUG, response->payload);
+    }
+
+    if (response->result < 4 && response->payload)
+    {
+        OIC_LOG_V(ERROR, TAG, "Sign Out error");
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "Sign Out OK");
+    }
+
+    SessionFree();
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+
+exit:
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Sends Sign Out request to cloud
+ *
+ * @param[in] ctx                    context
+ * @param[in] handle                 handle
+ * @param[in] response               response from peer
+ * @return  OCStackApplicationResult application result
+ */
+OCStackResult CloudSignOut(const OCDevAddr *endPoint)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (!endPoint)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: endPoint is NULL",__func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char *deviceId = getDeviceId();
+    if (!deviceId)
+    {
+        OIC_LOG(ERROR, TAG, "Cann't get the device id");
+        return OC_STACK_ERROR;
+    }
+
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
+    OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
+                              sessionObject.accesstoken);
+    OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, false);
+
+    char uri[MAX_URI_QUERY] = { 0, };
+    snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
+             endPoint->addr, endPoint->port,
+             OC_RSRVD_ACCOUNT_SESSION_URI);
+
+    OCCallbackData cbData;
+    memset(&cbData, 0, sizeof(OCCallbackData));
+    cbData.cb = handleCloudSignOutResponse;
+    cbData.cd = unlockMenu;
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL,
+                       (OCPayload *)payload,
+                       CT_ADAPTER_TCP,
+                       OC_LOW_QOS, &cbData, NULL, 0);
+}
+
diff --git a/resource/csdk/security/provisioning/sample/cloud/cloudAuth.h b/resource/csdk/security/provisioning/sample/cloud/cloudAuth.h
new file mode 100644 (file)
index 0000000..cc84050
--- /dev/null
@@ -0,0 +1,54 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#ifndef CLOUD_AUTH_H
+#define CLOUD_AUTH_H
+
+/**
+ * Sends Sign UP request to cloud
+ *
+ * @param[in] endPoint         peer endpoint
+ * @param[in] authProvider     authentication provider
+ * @param[in] authToken        authentication token
+ * @param[in] response         response callback
+ * @return  OCStackResult application result
+ */
+OCStackResult CloudSignUp(const OCDevAddr  *endPoint,
+                          const char *authProvider,
+                          const char *authToken);
+
+/**
+ * Sends Sign IN request to cloud
+ *
+ * @param[in] endPoint         peer endpoint
+ * @param[in] response         response callback
+ * @return  OCStackResult application result
+ */
+OCStackResult CloudSignIn(const OCDevAddr  *endPoint);
+
+/**
+ * Sends Sign OUT request to cloud
+ *
+ * @param[in] endPoint         peer endpoint
+ * @param[in] response         response callback
+ * @return  OCStackResult application result
+ */
+OCStackResult CloudSignOut(const OCDevAddr  *endPoint);
+
+#endif // CLOUD_AUTH_H
diff --git a/resource/csdk/security/provisioning/sample/cloud/cloudCommon.h b/resource/csdk/security/provisioning/sample/cloud/cloudCommon.h
new file mode 100644 (file)
index 0000000..1f617bc
--- /dev/null
@@ -0,0 +1,31 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#ifndef CLOUD_COMMON_H
+#define CLOUD_COMMON_H
+
+/**
+ * Used to sync with main menu
+ * Create this function to have proper API for delete callbacks
+ *
+ * @param[in] data         data
+ */
+void unlockMenu(void *data);
+
+#endif // CLOUD_COMMON_H
diff --git a/resource/csdk/security/provisioning/sample/cloud/cloudDiscovery.c b/resource/csdk/security/provisioning/sample/cloud/cloudDiscovery.c
new file mode 100644 (file)
index 0000000..f81c0fe
--- /dev/null
@@ -0,0 +1,230 @@
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+#include "payload_logging.h"
+#include "oic_string.h"
+#include "srmresourcestrings.h"
+#include "pmutility.h"
+
+#include "cloudCommon.h"
+#include "cloudWrapper.h"
+
+#define TAG "cloudDiscovery"
+
+#define DISCOVERY_URI "/oic/res"
+
+static OCDevAddr endPoint;
+static OCConnectivityType ocConnType = CT_DEFAULT;
+static char gUri[MAX_URI_LENGTH] = {0};
+
+bool withTcp = true;
+
+/**
+ * This function clears internal data
+ */
+static void clearData()
+{
+    memset(&endPoint, 0, sizeof(endPoint));
+    memset(gUri, 0, sizeof(gUri));
+    ocConnType = CT_DEFAULT;
+}
+
+/**
+ * This function parses Discovery payload
+ * It tries to find secure devices
+ *
+ * @param[in] clientResponse   response from peer
+ */
+static void parseClientResponse(OCClientResponse * clientResponse)
+{
+    OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
+
+    while (res)
+    {
+        char *uri = res->uri;
+        OIC_LOG_V(INFO, TAG, "Uri -- %s", uri);
+
+        if (0 == strcmp(uri, OIC_RSRC_DOXM_URI))
+        {
+            OIC_LOG(INFO,TAG,"Skip: doxm is secure virtual resource");
+            goto next;
+        }
+        if (0 == strcmp(uri, OIC_RSRC_PSTAT_URI))
+        {
+            OIC_LOG(INFO,TAG,"Skip: pstat is secure virtual resource");
+            goto next;
+        }
+
+        OIC_LOG_V(INFO, TAG, "Secure -- %s", res->secure ? "YES" : "NO");
+
+        if (res->secure)
+        {
+            ocConnType = clientResponse->connType;
+            endPoint = clientResponse->devAddr;
+
+            if(withTcp)
+            {
+                OIC_LOG_V(INFO,TAG,"SECUREPORT tcp: %d",res->tcpPort);
+                endPoint.port = res->tcpPort;
+            }
+            else
+            {
+                OIC_LOG_V(INFO,TAG,"SECUREPORT udp: %d",res->port);
+                endPoint.port = res->port;
+            }
+            OICStrcpy(gUri, sizeof(gUri), uri);
+            break;
+        }
+
+        next:
+        res = res->next;
+    }
+}
+
+/**
+ * This function handles discovery response
+ *
+ * @param[in] ctx                    context
+ * @param[in] handle                 handle
+ * @param[in] response               response from peer
+ * @return  OCStackApplicationResult application result
+ */
+static OCStackApplicationResult handleDiscoveryResponse(void *ctx, OCDoHandle handle,
+                                                        OCClientResponse * clientResponse)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+
+    if (NULL == clientResponse)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL response");
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    if (OC_STACK_OK == clientResponse->result)
+    {
+        OIC_LOG(INFO, TAG, "Discovery successful!");
+    }
+    else
+    {
+        OIC_LOG_V(INFO, TAG, "Discovery fails with result: %d", clientResponse->result);
+    }
+
+    if (clientResponse->payload)
+    {
+        OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload");
+    }
+
+    OIC_LOG_V(INFO, TAG,
+            "Device =============> Discovered @ %s:%d",
+            clientResponse->devAddr.addr,
+            clientResponse->devAddr.port);
+
+    parseClientResponse(clientResponse);
+
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+/**
+ * This function handles any response from secure device
+ *
+ * @param[in] ctx                    context
+ * @param[in] handle                 handle
+ * @param[in] response               response from peer
+ * @return  OCStackApplicationResult application result
+ */
+static OCStackApplicationResult handleResponse(void *ctx, OCDoHandle handle,
+                                               OCClientResponse * clientResponse)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+
+    if(!clientResponse)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: Received NULL response",  __func__);
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    if (NULL == ctx)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: Received NULL context, exit",  __func__);
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    char *str = NULL;
+    OCMethod method = *((OCMethod*)ctx);
+
+    switch (method)
+    {
+        case OC_REST_GET:
+            str = "Get";
+            break;
+        case OC_REST_PUT:
+            str = "Put";
+            break;
+        case OC_REST_POST:
+            str = "Post";
+            break;
+        default:
+            OIC_LOG_V(INFO, TAG, "Received Wrong method %d. Skip response", method);
+            return OC_STACK_ERROR;
+    }
+
+    OIC_LOG_V(INFO, TAG, "StackResult: %d",  clientResponse->result);
+    OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+    OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
+    OIC_LOG_V(INFO, TAG, "=============> %s Response", str);
+
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult InitDiscovery()
+{
+    clearData();
+
+    OCCallbackData cbData;
+    memset(&cbData, 0, sizeof(OCCallbackData));
+    cbData.cb = handleDiscoveryResponse;
+    cbData.cd = unlockMenu;
+
+    return OCDoResource(NULL, OC_REST_DISCOVER, DISCOVERY_URI, NULL, 0,
+                        CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult InitRequest(OCMethod method)
+{
+    if (0 == endPoint.port || 0 == endPoint.addr[0])
+    {
+        OIC_LOG(ERROR, TAG, "Host or port are missing. Please execute Discovery first!");
+        return OC_STACK_ERROR;
+    }
+
+    OCMethod *tmp = OICCalloc(1, sizeof(OCMethod));
+    if (!tmp)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate tmp");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    *tmp = method;
+
+    OIC_LOG_V(INFO, TAG, "Executing uri = %s", gUri);
+    OIC_LOG_V(INFO, TAG, "Send Request to %s:%d", endPoint.addr, endPoint.port);
+
+    endPoint.flags = (OCTransportFlags)(endPoint.flags | OC_SECURE);
+    endPoint.adapter = OC_ADAPTER_TCP;
+
+
+    OCCallbackData cbData;
+    memset(&cbData, 0, sizeof(OCCallbackData));
+    cbData.cd = unlockMenu;
+    cbData.cb = handleResponse;
+    cbData.context = (void *)tmp;
+
+    return OCDoResource(NULL, method, gUri, &endPoint, 0,
+                        ocConnType, OC_LOW_QOS, &cbData, NULL, 0);
+}
diff --git a/resource/csdk/security/provisioning/sample/cloud/cloudDiscovery.h b/resource/csdk/security/provisioning/sample/cloud/cloudDiscovery.h
new file mode 100644 (file)
index 0000000..e9ad6d4
--- /dev/null
@@ -0,0 +1,38 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#ifndef CLOUD_DISCOVERY_H
+#define CLOUD_DISCOVERY_H
+
+/**
+ * This function discovers devices
+ *
+ * @param[in] secure   secure flag
+ */
+OCStackResult InitDiscovery();
+
+/**
+ * This function sends GET/PUT/POST request to peer
+ * Peer info taken from previous discovery
+ *
+ * @param[in] method   request method
+ */
+OCStackResult InitRequest(OCMethod method);
+
+#endif // CLOUD_DISCOVERY_H
diff --git a/resource/csdk/security/provisioning/sample/cloud/cloudWrapper.c b/resource/csdk/security/provisioning/sample/cloud/cloudWrapper.c
new file mode 100644 (file)
index 0000000..3aa0eed
--- /dev/null
@@ -0,0 +1,594 @@
+#include "logger.h"
+#include "occloudprovisioning.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+#include "utils.h"
+
+#define TAG "CLOUD-WRAPPER"
+
+#define MAX_ID_LENGTH       (64)
+#define MAX_STRING_LENGTH   (256)
+
+#define UUID_EXAMPLE_1 "9cfbeb8e-5a1e-4d1c-9d01-2ae6fdb"
+#define UUID_EXAMPLE_2 "123e4567-e89b-12d3-a456-4266554"
+#define UUID_EXAMPLE_3 "987e6543-e21b-12d3-a456-4266554"
+#define SUBJECT_ID_EXAMPLE "72616E64-5069-6E44-6576-557569643030"
+
+#define ACL_ID_EXAMPLE "0f3d9f7fe5491d54077d"
+#define ACE_ID_EXAMPLE "a0001"
+
+#define ID_EXAMPLE_1   "78f98b4f25f21e2487e8"
+#define ID_EXAMPLE_2   "6caa7009386290fd3681"
+
+#define RESOURCE_URI_EXAMPLE "/a/light/0"
+#define RESOURCE_TYPE_EXAMPLE "core.light"
+#define INTERFACE_EXAMPLE "oic.if.baseline"
+
+//in case of optional parameters absence should be sent NULL
+#define OPTIONAL(str) (str[0] ? str : NULL)
+
+static bool readOptional(const char* description)
+{
+    if (NULL == description)
+    {
+        return false;
+    }
+
+    printf("Do you want to Enter %s (y/n):\n", description);
+    char choice = 0;
+
+    while(1)
+    {
+        scanf("%c", &choice);
+        getchar();
+
+        switch (choice)
+        {
+            case 'y': return true;
+            case 'n': return false;
+            default: printf("Wrong value entered. Please press 'y' or 'n'\n");
+        }
+    }
+    return false;
+}
+
+void readString(char* item, int length, const char* description, const char* example)
+{
+    printf("Enter %s (f.e. %s):\n", description, example);
+    char template[8] = { 0 };
+    snprintf(template, sizeof(template), "%%%ds", length - 1);
+    scanf(template, item);
+    getchar();
+}
+
+/**
+ * Read user input (expect string value, but it is optional and can be skipped by user)
+ *
+ * @param[out] item           string item to fill
+ * @param[in] length          max allowed string length
+ * @param[in] description     item description
+ * @param[in] example         item example
+ */
+static void readOptionalString(char* item, int length, const char* description, const char* example)
+{
+    if (readOptional(description))
+    {
+        readString(item, length, description, example);
+    }
+}
+
+void readInteger(int* item, const char* description, const char* example)
+{
+    printf("Enter %s (f.e. %s):\n", description, example);
+    scanf("%d", item);
+    getchar();
+}
+
+/**
+ * Read user input (expect array of strings)
+ *
+ * @param[out] list           array of strings structure
+ * @param[in] length          max allowed array item length
+ * @param[in] description     whole array description
+ * @param[in] example         array item example
+ */
+static void readStringArray(stringArray_t *list, int length, const char* description, const char* example)
+{
+    int i = 0;
+    int count = 0;
+    char hint[MAX_STRING_LENGTH] = { 0 };
+
+    snprintf(hint, sizeof(hint), "%s items count", description);
+    readInteger(&count, hint, "2");
+
+    char **item = NULL;
+
+    if (0 == count)
+    {
+        return;
+    }
+
+    item = OICCalloc(count, sizeof(char*));
+
+    if (NULL == item)
+    {
+        goto no_memory;
+    }
+
+    for (i = 0; i < count; i++)
+    {
+        item[i] = OICCalloc(length, sizeof(char));
+
+        if (NULL == item[i])
+        {
+            goto no_memory;
+        }
+
+        snprintf(hint, sizeof(hint), "%s %d item", description, i + 1);
+        readString(item[i], length, hint, example);
+    }
+    list->array  = item;
+    list->length = count;
+    return;
+
+no_memory:
+    //free already allocated memory here
+    for (int k = 0; k < i; k++)
+    {
+        OICFree(item[k]);
+    }
+    OICFree(item);
+}
+
+/**
+ * Read user input (expect array of strings)
+ * It is optional and can be skipped by user.
+ *
+ * @param[out] list           array of strings structure
+ * @param[in] length          max allowed array item length
+ * @param[in] description     whole array description
+ * @param[in] example         array item example
+ */
+static void readOptionalStringArray(stringArray_t *list, int length, const char* description, const char* example)
+{
+    if (readOptional(description))
+    {
+        readStringArray(list, length, description, example);
+    }
+}
+
+/**
+ * Copies whole binary file to crl variable
+ *
+ * @param[in] list           array of strings structure
+ * @param[out] crl           byte array to fill
+ * @return                   negative error code
+ * */
+static int ReadFile(const char *name, OCByteString *crl)
+{
+    FILE *file = NULL;
+    int length = 0;
+    uint8_t *buffer = NULL;
+    int result = 1;
+
+    //Open file
+    file = fopen(name, "rb");
+    if (!file)
+    {
+        OIC_LOG_V(ERROR, TAG, "Unable to open file %s", name);
+        return result;
+    }
+
+    //Get file length
+    result = fseek(file, 0, SEEK_END);
+    if (result)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to SEEK_END");
+        goto exit;
+    }
+
+    length = ftell(file);
+    if (length < 0)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to ftell");
+        goto exit;
+    }
+
+    result = fseek(file, 0, SEEK_SET);
+    if (result)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to SEEK_SET");
+        goto exit;
+    }
+
+    //Allocate memory
+    buffer = (uint8_t *)malloc(length);
+    if (!buffer)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to allocate buffer");
+        goto exit;
+    }
+
+    //Read file contents into buffer
+    size_t realLen = fread(buffer, length, 1, file);
+    if (realLen != (size_t)length)
+    {
+        OIC_LOG_V(ERROR, TAG, "Length mismatch: read %zu instead of %d bytes", realLen, length);
+        goto exit;
+    }
+
+    crl->bytes = buffer;
+    crl->len   = length;
+
+    result = 0;
+exit:
+    fclose(file);
+    return 0;
+}
+
+OCStackResult OCWrapperCertificateIssueRequest(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    return OCCloudCertificateIssueRequest(NULL, endPoint, callback);
+}
+
+OCStackResult OCWrapperGetCRL(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    return OCCloudGetCRL(NULL, endPoint, callback);
+}
+
+OCStackResult OCWrapperPostCRL(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCByteString crlData = {0, 0};
+    char filename[64] = {0};
+    char thisUpdate[16] = { 0 };
+    char nextUpdate[16] = { 0 };
+    stringArray_t serialNumbers = {0, 0};
+
+    readString(thisUpdate, sizeof(thisUpdate), "Crl's thisUpdate value", "20160727000000");
+    readString(nextUpdate, sizeof(nextUpdate), "Crl's nextUpdate value", "20161027000000");
+    readOptionalStringArray(&serialNumbers, 16, "Revoked serial numbers", "1234");
+
+    if (NULL == serialNumbers.array)
+    {
+        readString(filename, sizeof(filename),
+                   "filename from which binary Crl in DER format will be read", "crl");
+
+        if (ReadFile(filename, &crlData))
+        {
+            printf("Can't read crl from file %s\n", filename);
+            goto exit;
+        }
+    }
+    stringArray_t *rcsn = serialNumbers.array? &serialNumbers : NULL;
+    OCByteString *crl = crlData.bytes? &crlData : NULL;
+
+    result = OCCloudPostCRL(NULL, thisUpdate, nextUpdate, crl, rcsn,
+                            endPoint, callback);
+exit:
+    clearStringArray(&serialNumbers);
+    OICFree(crlData.bytes);
+
+    return result;
+}
+
+OCStackResult OCWrapperAclIdGetByDevice(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char di[MAX_ID_LENGTH] = { 0 };
+
+    readString(di, sizeof(di), "device id", UUID_EXAMPLE_1);
+
+    return OCCloudAclIdGetByDevice(NULL, di, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclIdCreate(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char oid[MAX_ID_LENGTH]  = { 0 };
+    char di[MAX_ID_LENGTH]   = { 0 };
+
+    readString(oid, sizeof(oid), "owner id", UUID_EXAMPLE_2);
+    readString(di, sizeof(di), "device id", UUID_EXAMPLE_1);
+
+    return OCCloudAclIdCreate(NULL, oid, di, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclIdDelete(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char aclid[MAX_ID_LENGTH] = { 0 };
+
+    readString(aclid, sizeof(aclid), "acl id", ACL_ID_EXAMPLE);
+
+    return OCCloudAclIdDelete(NULL, aclid, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclIndividualGetInfo(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char aclid[MAX_ID_LENGTH] = { 0 };
+
+    readString(aclid, sizeof(aclid), "acl id", ACL_ID_EXAMPLE);
+
+    return OCCloudAclIndividualGetInfo(NULL, aclid, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclIndividualUpdateAce(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    OCStackResult result = OC_STACK_NO_MEMORY;
+    int i = 0, j = 0;
+
+    char aclid[MAX_ID_LENGTH] = { 0 };
+    readString(aclid, sizeof(aclid), "ace id", ACL_ID_EXAMPLE);
+
+    int acllist_count = 0;
+    readInteger(&acllist_count, "acl list count", "1");
+
+    cloudAce_t *aces = OICCalloc(acllist_count, sizeof(cloudAce_t));
+    if (!aces)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate memory for aces");
+        goto exit;
+    }
+
+    for (i = 0; i < acllist_count; i++)
+    {
+        cloudAce_t *ace = &aces[i];
+        if (i != acllist_count - 1) ace->next = &aces[i + 1];
+
+        char aceid[MAX_ID_LENGTH] = { 0 };
+        char subjectuuid[MAX_ID_LENGTH] = { 0 };
+        int stype = 0;
+        int permission = 0;
+
+        readString(aceid, sizeof(aceid), "ace id", ACE_ID_EXAMPLE);
+        readString(subjectuuid, sizeof(subjectuuid), "subjectuuid", SUBJECT_ID_EXAMPLE);
+        readInteger(&stype, "subject type", "0 â€“ Device, 1 â€“ User, 2 - Group");
+        readInteger(&permission, "permission", "6");
+
+        ace->aceId = OICStrdup(aceid);
+        ace->stype = stype;
+        ace->permission = permission;
+        memcpy(&ace->subjectuuid, subjectuuid, sizeof(OicUuid_t));
+
+        int reslist_count = 0;
+        readInteger(&reslist_count, "resources list count", "1");
+
+        ace->resources = OICCalloc(reslist_count, sizeof(OicSecRsrc_t));
+        if (!ace->resources)
+        {
+            OIC_LOG(ERROR, TAG, "Can't allocate memory for resources");
+            goto exit;
+        }
+
+        for (j = 0; j < reslist_count; j++)
+        {
+            OicSecRsrc_t *res = &ace->resources[j];
+            if (j != reslist_count - 1) res->next = &ace->resources[j + 1];
+
+            char href[32] = { 0 };
+            readString(href, sizeof(href), "href", RESOURCE_URI_EXAMPLE);
+
+            stringArray_t rt = {0, 0};
+            readStringArray(&rt, MAX_ID_LENGTH, "resource type", RESOURCE_TYPE_EXAMPLE);
+
+            stringArray_t _if = {0, 0};
+            readStringArray(&_if, MAX_ID_LENGTH, "interface", INTERFACE_EXAMPLE);
+
+            res->href = OICStrdup(href);
+            res->types = rt.array;
+            res->typeLen = rt.length;
+            res->interfaces = _if.array;
+            res->interfaceLen = _if.length;
+        }
+    }
+
+    result = OCCloudAclIndividualUpdateAce(NULL, aclid, aces, endPoint, callback);
+exit:
+    if (aces)
+    {
+        for (int k = 0; k < i; k++)
+        {
+            cloudAce_t *ace = &aces[k];
+            OICFree(ace->aceId);
+
+            if (ace->resources)
+            {
+                for (int l = 0; l < j; l++)
+                {
+                    OicSecRsrc_t *res = &ace->resources[l];
+                    OICFree(res->href);
+
+                    stringArray_t rt = {.array = res->types, .length = res->typeLen};
+                    clearStringArray(&rt);
+
+                    stringArray_t _if = {.array = res->interfaces, .length = res->interfaceLen};
+                    clearStringArray(&_if);
+                }
+            }
+
+        }
+    }
+    return result;
+}
+
+OCStackResult OCWrapperAclIndividualDelete(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char aclid[MAX_ID_LENGTH] = { 0 };
+
+    readString(aclid, sizeof(aclid), "acl id", ACL_ID_EXAMPLE);
+
+    return OCCloudAclIndividualDelete(NULL, aclid, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclCreateGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char gtype[16] = { 0 };
+    char gmid[MAX_ID_LENGTH] = { 0 };
+
+    readString(gtype, sizeof(gtype), "Group type value", "Public");
+    readOptionalString(gmid, sizeof(gmid), "group member id value", UUID_EXAMPLE_2);
+
+    return OCCloudAclCreateGroup(NULL, gtype, OPTIONAL(gmid), endPoint, callback);
+}
+
+OCStackResult OCWrapperAclFindMyGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char mid[MAX_ID_LENGTH]  = { 0 };
+
+    readOptionalString(mid, sizeof(mid), "member id value", UUID_EXAMPLE_2);
+
+    return OCCloudAclFindMyGroup(NULL, OPTIONAL(mid), endPoint, callback);
+}
+
+OCStackResult OCWrapperAclDeleteGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char gid[MAX_ID_LENGTH]  = { 0 };
+    char gmid[MAX_ID_LENGTH] = { 0 };
+
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+
+    readOptionalString(gmid, sizeof(gmid), "group member id value", UUID_EXAMPLE_2);
+
+    return OCCloudAclDeleteGroup(NULL, gid, OPTIONAL(gmid), endPoint, callback);
+}
+
+OCStackResult OCWrapperAclJoinToInvitedGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char gid[MAX_ID_LENGTH]  = { 0 };
+
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+
+    return OCCloudAclJoinToInvitedGroup(NULL, gid, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclObserveGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char gid[MAX_ID_LENGTH]  = { 0 };
+
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+
+    return OCCloudAclObserveGroup(NULL, gid, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclShareDeviceIntoGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    OCStackResult result = OC_STACK_NO_MEMORY;
+    char gid[MAX_ID_LENGTH]  = { 0 };
+    stringArray_t midlist = {0,0};
+    stringArray_t dilist = {0,0};
+
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+
+    readStringArray(&midlist, MAX_ID_LENGTH, "member id list", UUID_EXAMPLE_2);
+
+    readStringArray(&dilist, MAX_ID_LENGTH, "device list", UUID_EXAMPLE_1);
+
+    result = OCCloudAclShareDeviceIntoGroup(NULL, gid, &midlist, &dilist, endPoint, callback);
+
+    clearStringArray(&midlist);
+    clearStringArray(&dilist);
+
+    return result;
+}
+
+OCStackResult OCWrapperAclDeleteDeviceFromGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    OCStackResult result = OC_STACK_NO_MEMORY;
+    char gid[MAX_ID_LENGTH]  = { 0 };
+    stringArray_t midlist = {0,0};
+    stringArray_t dilist = {0,0};
+
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+
+    readStringArray(&midlist, MAX_ID_LENGTH, "member id list", UUID_EXAMPLE_2);
+
+    readStringArray(&dilist, MAX_ID_LENGTH, "device list", UUID_EXAMPLE_1);
+
+    result = OCCloudAclDeleteDeviceFromGroup(NULL, gid, &midlist, &dilist, endPoint, callback);
+
+    clearStringArray(&midlist);
+    clearStringArray(&dilist);
+
+    return result;
+}
+
+OCStackResult OCWrapperAclGroupGetInfo(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char gid[MAX_ID_LENGTH]  = { 0 };
+    char mid[MAX_ID_LENGTH]  = { 0 };
+
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+
+    readOptionalString(mid, sizeof(mid), "member id value", UUID_EXAMPLE_2);
+
+    return OCCloudAclGroupGetInfo(NULL, gid, OPTIONAL(mid), endPoint, callback);
+}
+
+OCStackResult OCWrapperAclInviteUser(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    OCStackResult result = OC_STACK_NO_MEMORY;
+    char uid[MAX_ID_LENGTH]  = { 0 };
+    stringArray_t midlist = {0,0};
+    stringArray_t gidlist = {0,0};
+
+    readOptionalString(uid, sizeof(uid), "user id value", UUID_EXAMPLE_2);
+
+    readStringArray(&gidlist, MAX_ID_LENGTH, "group id list", UUID_EXAMPLE_1);
+
+    readStringArray(&midlist, MAX_ID_LENGTH, "member id list", UUID_EXAMPLE_2);
+
+    result = OCCloudAclInviteUser(NULL, OPTIONAL(uid), &gidlist, &midlist, endPoint, callback);
+
+    clearStringArray(&midlist);
+    clearStringArray(&gidlist);
+
+    return result;
+}
+
+OCStackResult OCWrapperAclGetInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char uid[MAX_ID_LENGTH]  = { 0 };
+
+    readOptionalString(uid, sizeof(uid), "user uuid value", UUID_EXAMPLE_2);
+
+    return OCCloudAclGetInvitation(NULL, OPTIONAL(uid), endPoint, callback);
+}
+
+OCStackResult OCWrapperAclDeleteInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char uid[MAX_ID_LENGTH]  = { 0 };
+    char gid[MAX_ID_LENGTH]  = { 0 };
+
+    readOptionalString(uid, sizeof(uid), "user uuid value", UUID_EXAMPLE_2);
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+
+    return OCCloudAclDeleteInvitation(NULL, OPTIONAL(uid), gid, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclCancelInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char uid[MAX_ID_LENGTH]  = { 0 };
+    char gid[MAX_ID_LENGTH]  = { 0 };
+    char mid[MAX_ID_LENGTH]  = { 0 };
+
+    readOptionalString(uid, sizeof(uid), "user uuid value", UUID_EXAMPLE_2);
+
+    readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
+    readString(mid, sizeof(mid), "member id value", ID_EXAMPLE_1);
+
+    return OCCloudAclCancelInvitation(NULL, OPTIONAL(uid), gid, mid, endPoint, callback);
+}
+
+OCStackResult OCWrapperAclPolicyCheck(const OCDevAddr *endPoint, OCCloudResponseCB callback)
+{
+    char sid[MAX_ID_LENGTH] = { 0 };
+    char di[MAX_ID_LENGTH]  = { 0 };
+    char rm[16]  = { 0 };
+    char user_uri[32] = { 0 };
+
+    readString(sid, sizeof(sid), "subject id", UUID_EXAMPLE_1);
+    readString(di, sizeof(di), "device id", UUID_EXAMPLE_2);
+    readString(rm, sizeof(rm), "request method", "GET or POST or DELETE");
+    readString(user_uri, sizeof(user_uri), "request uri", RESOURCE_URI_EXAMPLE);
+
+    return OCCloudAclPolicyCheck(NULL, sid, di, rm, user_uri, endPoint, callback);
+}
diff --git a/resource/csdk/security/provisioning/sample/cloud/cloudWrapper.h b/resource/csdk/security/provisioning/sample/cloud/cloudWrapper.h
new file mode 100644 (file)
index 0000000..a8f3116
--- /dev/null
@@ -0,0 +1,243 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#ifndef OC_CLOUD_WRAPPER_H
+#define OC_CLOUD_WRAPPER_H
+
+#include "occloudprovisioning.h"
+
+/**
+ * Certificate-Issue request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperCertificateIssueRequest(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * CRL GET request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperGetCRL(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * CRL POST request function (with Serial Numbers list to revoke)
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperPostCRL(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL id retrieve by device id
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclIdGetByDevice(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL id create
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclIdCreate(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL id delete
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclIdDelete(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL individual get info
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclIndividualGetInfo(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL individual update ACE
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclIndividualUpdateAce(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL individual delete
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclIndividualDelete(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL post group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclCreateGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL get group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclFindMyGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL delete group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclDeleteGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL join to invited group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclJoinToInvitedGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL observe group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclObserveGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL share device into group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclShareDeviceIntoGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL delete device from group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclDeleteDeviceFromGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL get group info request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclGroupGetInfo(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL invite user to group request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclInviteUser(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL get invitation request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclGetInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL delete invitation request function (by receiver)
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclDeleteInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL cancel invitation request function (by sender)
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclCancelInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * ACL check that given request can be applied to resource
+ *
+ * @param[in] endPoint          cloud host and port
+ * @param[in] callback          result callback
+ * @return  OCStackResult application result
+ */
+OCStackResult OCWrapperAclPolicyCheck(const OCDevAddr *endPoint, OCCloudResponseCB callback);
+
+/**
+ * Read user input (expect string value)
+ *
+ * @param[out] item           string item to fill
+ * @param[in] length          max allowed string length
+ * @param[in] description     item description
+ * @param[in] example         item example
+ */
+void readString(char* item, int length, const char* description, const char* example);
+
+/**
+ * Read user input (expect integer value)
+ *
+ * @param[out] item           integer item to fill
+ * @param[in] description     item description
+ * @param[in] example         item example
+ */
+void readInteger(int* item, const char* description, const char* example);
+
+
+#endif //OC_CLOUD_WRAPPER_H
diff --git a/resource/csdk/security/provisioning/sample/cloudClient.c b/resource/csdk/security/provisioning/sample/cloudClient.c
new file mode 100644 (file)
index 0000000..d3a1aa0
--- /dev/null
@@ -0,0 +1,523 @@
+//******************************************************************
+//
+// Copyright 2016 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ocstack.h"
+#include "logger.h"
+#include "camutex.h"
+#include "cathreadpool.h"
+#include "ocpayload.h"
+#include "payload_logging.h"
+#include "ocprovisioningmanager.h"
+
+#include "utils.h"
+#include "cloudAuth.h"
+#include "cloudWrapper.h"
+#include "cloudDiscovery.h"
+
+#ifdef __unix__
+#include <unistd.h> //for unlink
+#endif
+
+#define TAG "cloudClient"
+
+#define DEFAULT_HOST            "10.113.68.85"//"127.0.0.1"
+#define DEFAULT_PORT            OC_MULTICAST_PORT
+#define DEFAULT_DEVICEID        "6A757374-776F-726B-4465-765575696430"
+#define DEFAULT_USERID          "6A757374-776F-726B-4465-765575696430"
+#define DEFAULT_AUTH_PROVIDER   "github"
+#define DEFAULT_DB_FILE         "./cloud.dat"
+#define DEFAULT_RESPONSE_WAIT_TIME (10 * 1000000) //10s
+
+#define GITHUB_AUTH_LINK        "https://github.com/login?return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3Dea9c18f540323b0213d0%26redirect_uri%3Dhttp%253A%252F%252Fwww.example.com%252Foauth_callback%252F"
+
+static bool fExit = false;
+
+static OCDevAddr endPoint;
+static char token[1024];
+static char authProvider[1024];
+static char *fname = DEFAULT_DB_FILE;
+static uint64_t timeout;
+static uint16_t g_credId = 0;
+
+ca_cond cond;
+ca_mutex mutex;
+
+typedef enum {
+    SIGN_UP       = 1,
+    SIGN_IN       = 2,
+    SIGN_OUT      = 3,
+
+    HOST          = 4,
+    PORT          = 5,
+    DB_FILE       = 6,
+    AUTH_PROVIDER = 7,
+    USE_RSA = 8,
+    SAVE_TRUST_CERT = 9,
+    USE_SECURE_CONN = 10,
+
+    DISCOVERY     = 13,
+    GET           = 14,
+    PUT           = 15,
+    POST          = 16,
+
+    CSR_SIGN      = 19,
+
+    CRL_GET       = 20,
+    CRL_POST      = 21,
+
+    ACL_ID_CREATE = 30,
+    ACL_ID_GET_BY_DEVICE = 31,
+    ACL_ID_DELETE = 32,
+
+    ACL_INDIVIDUAL_GET_INFO = 40,
+    ACL_INDIVIDUAL_UPDATE_ACE = 41,
+    ACL_INDIVIDUAL_DELETE = 42,
+
+    ACL_GROUP_CREATE = 50,
+    ACL_GROUP_FIND   = 51,
+    ACL_GROUP_JOIN   = 52,
+    ACL_GROUP_OBSERVE= 53,
+    ACL_GROUP_DELETE = 54,
+
+    ACL_GROUP_SHARE_DEVICE  = 60,
+    ACL_GROUP_DELETE_DEVICE  = 61,
+    ACL_GROUP_GET_INFO  = 62,
+
+    ACL_POLICY_CHECK_REQUEST = 70,
+
+    ACL_GROUP_INVITE_USER = 80,
+    ACL_GROUP_GET_INVITE  = 81,
+    ACL_GROUP_DELETE_INVITE  = 82,
+    ACL_GROUP_CANCEL_INVITE  = 83,
+
+    EXIT          = 99
+}CloudRequest;
+
+void printMenu()
+{
+    printf("************************************************************\n");
+    printf("****************** Cloud Client Requests *******************\n");
+    printf("************************************************************\n");
+    printf("** AUTHORIZATION\n");
+    printf("** %d - Sign Up request\n", SIGN_UP);
+    printf("** %d - Sign In request\n", SIGN_IN);
+    printf("** %d - Sign Out request\n", SIGN_OUT);
+
+    printf("** SETTINGS \n");
+    printf("** %d - Change default host\n", HOST);
+    printf("** %d - Change default port\n", PORT);
+    printf("** %d - Change default database filename\n", DB_FILE);
+    printf("** %d - Change default auth provider\n", AUTH_PROVIDER);
+    printf("** %d - Change TLS cipher suite to RSA\n", USE_RSA);
+    printf("** %d - Save Trust Cert. Chain into Cred of SVR\n", SAVE_TRUST_CERT);
+    printf("** %d - Change Protocol type (CoAP/CoAPs)\n", USE_SECURE_CONN);
+
+    printf("** DISCOVERY\n");
+    printf("** %d - Start Discovery\n", DISCOVERY);
+    printf("** %d - Get Request\n", GET);
+    printf("** %d - Put Request\n", PUT);
+    printf("** %d - Post Request\n", POST);
+
+    printf("** CERTIFICATE REQUEST\n");
+    printf("** %d - Certificate Request\n", CSR_SIGN);
+
+    printf("** CRL\n");
+    printf("** %d - CRL GET Request\n", CRL_GET);
+    printf("** %d - CRL POST Request\n", CRL_POST);
+
+    printf("** ACL MANAGER\n");
+    printf("** %d - ACL id create Request\n", ACL_ID_CREATE);
+    printf("** %d - ACL id retrieve by device Request\n", ACL_ID_GET_BY_DEVICE);
+    printf("** %d - ACL id delete Request\n", ACL_ID_DELETE);
+
+    printf("** ACL INDIVIDUAL\n");
+    printf("** %d - ACL individual get info Request\n", ACL_INDIVIDUAL_GET_INFO);
+    printf("** %d - ACL individual update ACE Request\n", ACL_INDIVIDUAL_UPDATE_ACE);
+    printf("** %d - ACL individual delete Request\n", ACL_INDIVIDUAL_DELETE);
+
+    printf("** ACL GROUP MANAGER\n");
+    printf("** %d - ACL Create Group Request\n", ACL_GROUP_CREATE);
+    printf("** %d - ACL Find Group Request\n", ACL_GROUP_FIND);
+    printf("** %d - ACL Join to invited Group Request\n", ACL_GROUP_JOIN);
+    printf("** %d - ACL Observe Group Request\n", ACL_GROUP_OBSERVE);
+    printf("** %d - ACL Delete Group Request\n", ACL_GROUP_DELETE);
+
+    printf("** ACL INDIVIDUAL GROUP\n");
+    printf("** %d - ACL Share device into Group Request\n", ACL_GROUP_SHARE_DEVICE);
+    printf("** %d - ACL Delete device from Group Request\n", ACL_GROUP_DELETE_DEVICE);
+    printf("** %d - ACL Get Group Info Request\n", ACL_GROUP_GET_INFO);
+
+    printf("** ACL POLICY ENFORCEMENT\n");
+    printf("** %d - ACL Check Permissions Request\n", ACL_POLICY_CHECK_REQUEST);
+
+    printf("** ACL MEMBER INVITATION\n");
+    printf("** %d - ACL Invite user to group Request\n", ACL_GROUP_INVITE_USER);
+    printf("** %d - ACL Retrieve invitation Request\n", ACL_GROUP_GET_INVITE);
+    printf("** %d - ACL Delete invitation Request\n", ACL_GROUP_DELETE_INVITE);
+    printf("** %d - ACL Cancel invitation Request\n", ACL_GROUP_CANCEL_INVITE);
+
+    printf("** EXIT\n");
+    printf("** %d - Exit cloud client\n\n", EXIT);
+    printf("************************************************************\n");
+
+    printf(">> Enter Menu number:\n");
+}
+
+void unlockMenu(void *data)
+{
+    OICFree(data);
+
+    ca_mutex_lock(mutex);
+    ca_cond_signal(cond);
+    ca_mutex_unlock(mutex);
+}
+
+/**
+ * This is default callback to all requests
+ * Used to sync with main menu
+ *
+ * @param[in] ctx          context
+ * @param[in] result       result
+ * @param[in] data         data
+ */
+static void handleCB(void* ctx, OCStackResult result, void* data)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(data);
+
+    OIC_LOG_V(INFO, TAG, "%s: Received result = %d", __func__, result);
+
+    unlockMenu(NULL);
+}
+
+static int saveTrustCert(void)
+{
+    OCStackResult res = OC_STACK_ERROR;
+    OIC_LOG(INFO, TAG, "Save Trust Cert. Chain into Cred of SVR");
+
+    ByteArray trustCertChainArray = {0, 0};
+
+    FILE *fp = fopen("rootca.crt", "rb+");
+
+    if (fp)
+    {
+        size_t fsize;
+        if (fseeko(fp, 0, SEEK_END) == 0 && (fsize = ftello(fp)))
+        {
+            trustCertChainArray.data = OICCalloc(1, fsize+1);
+            trustCertChainArray.len = fsize+1;
+            if (NULL == trustCertChainArray.data)
+            {
+                OIC_LOG(ERROR,TAG,"OICCalloc");
+                fclose(fp);
+                return res;
+            }
+            rewind(fp);
+            fsize = fread(trustCertChainArray.data, 1, fsize, fp);
+            fclose(fp);
+        }
+    }
+    OIC_LOG_BUFFER(DEBUG, TAG, trustCertChainArray.data, trustCertChainArray.len);
+
+    res = OCSaveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len, OIC_ENCODING_PEM,&g_credId);
+
+    if(OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "OCSaveTrustCertChainBin API error");
+        return res;
+    }
+    OIC_LOG_V(INFO, TAG, "CredId of Saved Trust Cert. Chain into Cred of SVR : %d.\n", g_credId);
+
+    return res;
+}
+
+static void userRequests()
+{
+    //defaults
+    memset(token, 0, sizeof(token));
+    memset(authProvider, 0, sizeof(authProvider));
+    strncpy(authProvider, DEFAULT_AUTH_PROVIDER, sizeof(authProvider));
+    memset(&endPoint, 0, sizeof(endPoint));
+    strncpy(endPoint.addr, DEFAULT_HOST, sizeof(endPoint.addr));
+    endPoint.port = DEFAULT_PORT;
+
+    mutex = ca_mutex_new();
+    cond = ca_cond_new();
+
+    while (false == fExit)
+    {
+        OCStackResult res = OC_STACK_ERROR;
+        timeout = DEFAULT_RESPONSE_WAIT_TIME;
+        //startup report
+        printf("-----------------------------------------------------------\n");
+        printf("Connecting to: %s:%d\n", endPoint.addr, endPoint.port);
+        printf("via auth provider: %s\n", authProvider);
+        printf("srv file: %s\n", fname);
+        printf("CoAP prefix: %s\n", DEFAULT_PREFIX);
+        printf("-----------------------------------------------------------\n");
+
+        printMenu();
+
+        int request = 0;
+        scanf("%d", &request);
+
+        switch (request)
+        {
+        case SIGN_UP:
+            if (0 == strncmp(authProvider, DEFAULT_AUTH_PROVIDER, sizeof(authProvider)))
+            {
+                printf("Paste to browser %s and get auth code\n", GITHUB_AUTH_LINK);
+            }
+            readString(token, sizeof(token), "auth token", "check link above");
+            res = CloudSignUp(&endPoint, authProvider, token);
+            break;
+        case SIGN_IN:
+            res = CloudSignIn(&endPoint);
+            break;
+        case SIGN_OUT:
+            res = CloudSignOut(&endPoint);
+            break;
+        case HOST:
+            readString(endPoint.addr, sizeof(endPoint.addr), "host ip address", DEFAULT_HOST);
+            break;
+        case PORT:
+        {
+            char example[8];
+            snprintf(example, sizeof(example), "%d", DEFAULT_PORT);
+            int tmp = 0;
+            readInteger(&tmp, "port number", example);
+            endPoint.port = tmp;
+        }
+        break;
+        case CRL_GET:
+            res = OCWrapperGetCRL(&endPoint, handleCB);
+            break;
+        case CRL_POST:
+            res = OCWrapperPostCRL(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_CREATE:
+            res = OCWrapperAclCreateGroup(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_FIND:
+            res = OCWrapperAclFindMyGroup(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_DELETE:
+            res = OCWrapperAclDeleteGroup(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_JOIN:
+            res = OCWrapperAclJoinToInvitedGroup(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_OBSERVE:
+            res = OCWrapperAclObserveGroup(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_SHARE_DEVICE:
+            res = OCWrapperAclShareDeviceIntoGroup(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_DELETE_DEVICE:
+            res = OCWrapperAclDeleteDeviceFromGroup(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_GET_INFO:
+            res = OCWrapperAclGroupGetInfo(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_INVITE_USER:
+            res = OCWrapperAclInviteUser(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_GET_INVITE:
+            res = OCWrapperAclGetInvitation(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_DELETE_INVITE:
+            res = OCWrapperAclDeleteInvitation(&endPoint, handleCB);
+            break;
+        case ACL_GROUP_CANCEL_INVITE:
+            res = OCWrapperAclCancelInvitation(&endPoint, handleCB);
+            break;
+        case ACL_POLICY_CHECK_REQUEST:
+            res = OCWrapperAclPolicyCheck(&endPoint, handleCB);
+            break;
+        case ACL_ID_GET_BY_DEVICE:
+            res = OCWrapperAclIdGetByDevice(&endPoint, handleCB);
+            break;
+        case ACL_ID_CREATE:
+            res = OCWrapperAclIdCreate(&endPoint, handleCB);
+            break;
+        case ACL_ID_DELETE:
+            res = OCWrapperAclIdDelete(&endPoint, handleCB);
+            break;
+        case ACL_INDIVIDUAL_GET_INFO:
+            res = OCWrapperAclIndividualGetInfo(&endPoint, handleCB);
+            break;
+        case ACL_INDIVIDUAL_UPDATE_ACE:
+            res = OCWrapperAclIndividualUpdateAce(&endPoint, handleCB);
+            break;
+        case ACL_INDIVIDUAL_DELETE:
+            res = OCWrapperAclIndividualDelete(&endPoint, handleCB);
+            break;
+        case CSR_SIGN:
+            res = OCWrapperCertificateIssueRequest(&endPoint, handleCB);
+            break;
+        case DISCOVERY:
+            res = InitDiscovery();
+            break;
+        case GET:
+            res = InitRequest(OC_REST_GET);
+            break;
+        case PUT:
+            res= InitRequest(OC_REST_PUT);
+            break;
+        case POST:
+            res= InitRequest(OC_REST_POST);
+            break;
+        case USE_RSA:
+            CASelectCipherSuite(0x35, CA_ADAPTER_TCP);
+            break;
+        case SAVE_TRUST_CERT:
+            saveTrustCert();
+            break;
+        case USE_SECURE_CONN:
+        {
+            int tmp = 0;
+            readInteger(&tmp, "CoAP protocol type", "0 - non-secure, 1 - secure");
+            setCoapPrefix(0 == tmp ? false : true);
+        }
+            break;
+        case EXIT:
+            ca_mutex_free(mutex);
+            ca_cond_free(cond);
+            fExit = true;
+            break;
+        default:
+            printf(">> Entered Wrong Menu Number. Please Enter Again\n\n");
+            break;
+        }
+
+        //if requests were sent then wait response
+        if (res == OC_STACK_OK)
+        {
+            ca_mutex_lock(mutex);
+            ca_cond_wait_for(cond, mutex, timeout);
+            ca_mutex_unlock(mutex);
+        }
+    }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+    OC_UNUSED(path);
+    return fopen(fname, mode);
+}
+
+/**
+ * Check file accessibility
+ *
+ * @param[in] name        file path
+ * @return true           if check was successful
+ */
+static bool checkConfig(const char *name)
+{
+    FILE* file = fopen(name, "rb");
+
+    if (file)
+    {
+        fclose(file);
+        return true;
+    }
+    return false;
+}
+
+static void printUsage(char *name)
+{
+    printf("Wrong arguments count!\n");
+    printf("Usage : %s <database_filename>\n", name);
+    printf("Examples : 1) %s 2) %s cloud.dat\n", name, name);
+}
+
+//==============================================================
+int main(int argc, char *argv[])
+{
+    OC_UNUSED(argc);
+    OC_UNUSED(argv);
+
+    if (2 == argc)
+    {
+        fname = argv[1];
+
+        if (!checkConfig(fname))
+        {
+            OIC_LOG_V(ERROR, TAG, "Can't open database file %s, exit!", fname);
+            return -1;
+        }
+    }
+    else if (argc > 2)
+    {
+        printUsage(argv[0]);
+    }
+
+    //Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
+
+    OCRegisterPersistentStorageHandler(&ps);
+
+    OCMode stackMode = OC_CLIENT_SERVER;
+    if (OCInit(NULL, 0, stackMode) != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack init error, exit\n");
+        return 1;
+    }
+
+    ca_thread_pool_t g_threadPoolHandle = NULL;
+    CAResult_t res = ca_thread_pool_init(1, &g_threadPoolHandle);
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "thread pool initialize error.");
+        return res;
+    }
+
+    res = ca_thread_pool_add_task(g_threadPoolHandle, userRequests, NULL);
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "thread pool add task error.");
+        goto error;
+    }
+
+    while(false == fExit)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG,"OCProcess process error, exit\n");
+            return 2;
+        }
+    }
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStop process error\n");
+    }
+
+    error:
+    if (g_threadPoolHandle)
+    {
+        ca_thread_pool_free(g_threadPoolHandle);
+    }
+
+    return 0;
+}
diff --git a/resource/csdk/security/provisioning/sample/rootca.crt b/resource/csdk/security/provisioning/sample/rootca.crt
new file mode 100644 (file)
index 0000000..54ec780
--- /dev/null
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeYCAQEwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV
+BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
+ZDAeFw0xNjA2MjgwNTMzNThaFw0yNjA2MjYwNTMzNThaMEUxCzAJBgNVBAYTAkFV
+MRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRz
+IFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1HHkfMG9c
+BJ7ZeCIBKe7pSjpptvi+hzpdV72W7szpWDlTQdUaRxKL9aoNxbyuF5OL8xAQ9s28
+IqIxdPW7X3JAmkLigzMCo2xtXHz/OyvomU6fhibneQw5De+iUoD68zdG+/k1NcAW
+xx+VEAMw4fvZvYSVEQ1aKFnjtrQ8o6Zfe5+MRTvBq+G0+jwZWJEoKbpxIPpNWPGx
+AV17tEpe+lg27jEYDYG1QUiL2TG80ZjQQL95OjETYf8EIxoqrKHvHCvDin0zdd+E
+qPN0Y+Rhkl3PYoxWm7d8z0p1mD7lcwOMvy1KgEgtJ7SHy0D2SIW/KaDox/kRPC1P
+ksFeAS2B0Z9zAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAtHjimMywXn893Ifu1v
+tNnL9ITMpQhsHAlg1QBVEyjGZLIjUgMhsWljVwTC1PdBrO7V0ElYbeV+LKYGwDk6
+fjBJogCLgZiUw18F8TjHC/qDsoWEsm1iB4KcTZkk0nm/2vidHK0TMLzCohR71/vN
+KS2rtiQDYGKe9EzjNSO3GlCWkVTYtJNhALa/BfDza5keRkwmldJYhlx4rQH5yVRn
+t5k87vjX0h7m8MzIwiAb2s/b9XBlM1FuFx3FxcVjBl7KtUAU7twU8v5LenjWDSH1
+D1jnKiZUUspgovhosPRqmxGNXldaX1E+RJmxdtqUVg4co/zjAbTY7C+7ZYIZBo46
+Ll0=
+-----END CERTIFICATE-----
diff --git a/resource/csdk/security/provisioning/src/cloud/aclgroup.c b/resource/csdk/security/provisioning/src/cloud/aclgroup.c
new file mode 100644 (file)
index 0000000..ea38b53
--- /dev/null
@@ -0,0 +1,305 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "utils.h"
+
+#include "oic_malloc.h"
+#include "logger.h"
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "pmutility.h"
+#include "cacommonutil.h"
+
+#define TAG "CLOUD-ACL-GROUP"
+
+/**
+ * ACL create group request received data handler
+ *
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult handleAclCreateGroupResponse(void *ctx, void **data, OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    if (NULL == response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char *gid = NULL;
+
+    if (!OCRepPayloadGetPropString((const OCRepPayload *)response->payload, OC_RSRVD_GROUP_ID, &gid))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_GROUP_ID);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    *data = gid;
+    return OC_STACK_OK;
+}
+
+/**
+ * ACL find my group received data handler
+ *
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult handleAclFindMyGroupResponse(void *ctx, void **data, OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    if (NULL == response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    const OCRepPayload *payload = (const OCRepPayload *)response->payload;
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+
+    stringArray_t *gidlist = OICCalloc(1, sizeof(stringArray_t));
+    if (NULL == gidlist)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate gidlist");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    if (!OCRepPayloadGetStringArray(payload, OC_RSRVD_GROUP_ID_LIST, &gidlist->array, dimensions))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_GROUP_ID_LIST);
+        OICFree(gidlist);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    gidlist->length = calcDimTotal(dimensions);
+
+    *data = gidlist;
+    return OC_STACK_OK;
+}
+
+OCStackResult OCCloudAclCreateGroup(void* ctx,
+                                    const char *groupType,
+                                    const char *groupMasterId,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(groupType, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleAclCreateGroupResponse, NULL);
+
+    OCRepPayload *payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_GROUP_TYPE, groupType);
+
+    //add next fields if they were filled
+    if (groupMasterId) OCRepPayloadSetPropString(payload, OC_RSRVD_GROUP_MASTER_ID, groupMasterId);
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclFindMyGroup(void* ctx,
+                                    const char *memberId,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL);
+
+    if (memberId)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_MEMBER_ID, memberId);
+    }
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleAclFindMyGroupResponse, NULL);
+
+    return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclDeleteGroup(void* ctx,
+                                    const char *groupId,
+                                    const char *groupMasterId,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL, OC_RSRVD_GROUP_ID, groupId);
+
+    if (groupMasterId)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_GROUP_MASTER_ID, groupMasterId);
+    }
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclJoinToInvitedGroup(void* ctx,
+                                           const char *groupId,
+                                           const OCDevAddr *endPoint,
+                                           OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL, groupId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclObserveGroup(void* ctx,
+                                     const char *groupId,
+                                     const OCDevAddr *endPoint,
+                                     OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL, groupId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_OBSERVE, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclShareDeviceIntoGroup(void* ctx,
+                                             const char *groupId,
+                                             const stringArray_t *memberIds,
+                                             const stringArray_t *deviceIds,
+                                             const OCDevAddr *endPoint,
+                                             OCCloudResponseCB callback)
+{
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(memberIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(deviceIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL, groupId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    OCRepPayload *payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    dimensions[0] = memberIds->length;
+    OCRepPayloadSetStringArray(payload, OC_RSRVD_MEMBER_ID_LIST,
+                               (const char **)memberIds->array, dimensions);
+    dimensions[0] = deviceIds->length;
+    OCRepPayloadSetStringArray(payload, OC_RSRVD_DEVICE_ID_LIST,
+                               (const char **)deviceIds->array, dimensions);
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclDeleteDeviceFromGroup(void* ctx,
+                                              const char *groupId,
+                                              const stringArray_t *memberIds,
+                                              const stringArray_t *deviceIds,
+                                              const OCDevAddr *endPoint,
+                                              OCCloudResponseCB callback)
+
+{
+    char uri[MAX_URI_LENGTH * 4] = { 0 };
+    int max_size = sizeof(uri);
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(memberIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(deviceIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, max_size, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL, groupId);
+
+    for (size_t i = 0; i < memberIds->length; i++)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, max_size - len, "%c%s=%s", (0 == i)?'?':'&',
+                OC_RSRVD_MEMBER_ID_LIST, memberIds->array[i]);
+    }
+
+    for (size_t i = 0; i < deviceIds->length; i++)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, max_size - len, "%c%s=%s",
+                (0 == i && 0 == memberIds->length)?'?':'&',
+                OC_RSRVD_DEVICE_ID_LIST, deviceIds->array[i]);
+    }
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclGroupGetInfo(void* ctx,
+                                     const char *groupId,
+                                     const char *memberId,
+                                     const OCDevAddr *endPoint,
+                                     OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_GROUP_URL, groupId);
+
+    if (memberId)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_MEMBER_ID, memberId);
+    }
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
diff --git a/resource/csdk/security/provisioning/src/cloud/aclid.c b/resource/csdk/security/provisioning/src/cloud/aclid.c
new file mode 100644 (file)
index 0000000..e698e34
--- /dev/null
@@ -0,0 +1,321 @@
+#include "utils.h"
+
+#include "oic_malloc.h"
+#include "logger.h"
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "pmutility.h"
+#include "cacommonutil.h"
+#include "aclresource.h"
+#include "ocpayloadcbor.h"
+#include "payload_logging.h"
+
+#define TAG "CLOUD-ACL-ID"
+
+/**
+ * ACL Id create request received data handler
+ *
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult handleAclIdCreateResponse(void *ctx, void **data, OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    if (NULL == response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char *aclid = NULL;
+
+    if (!OCRepPayloadGetPropString((const OCRepPayload *)response->payload, OC_RSRVD_ACL_ID, &aclid))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_ACL_ID);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    *data = aclid;
+    return OC_STACK_OK;
+}
+
+OCStackResult OCCloudAclIdGetByDevice(void* ctx,
+                                      const char *deviceId,
+                                      const OCDevAddr *endPoint,
+                                      OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, OC_RSRVD_DEVICE_ID, deviceId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleAclIdCreateResponse, NULL);
+
+    return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclIdCreate(void* ctx,
+                                 const char *ownerId,
+                                 const char *deviceId,
+                                 const OCDevAddr *endPoint,
+                                 OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(ownerId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s&%s=%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL,
+            OC_RSRVD_OWNER_ID, ownerId, OC_RSRVD_DEVICE_ID, deviceId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleAclIdCreateResponse, NULL);
+
+    return OCDoResource(NULL, OC_REST_PUT, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclIdDelete(void* ctx,
+                                 const char *aclId,
+                                 const OCDevAddr *endPoint,
+                                 OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH]  = { 0 };
+
+    VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, OC_RSRVD_ACL_ID, aclId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+/**
+ * ACL Get Info received data handler
+ *
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult handleAclGetInfoResponse(void *ctx, void **data, OCClientResponse *response)
+{
+    OCStackResult result = OC_STACK_OK;
+    uint8_t *cbor = NULL;
+    size_t size   = 0;
+
+    OC_UNUSED(ctx);
+    OC_UNUSED(data);
+
+    if (NULL == response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload\n");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    result = OCConvertPayload(response->payload, &cbor, &size);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "Can't convert OCPayload to cbor");
+        goto exit;
+    }
+
+    OicSecAcl_t* acl = CBORPayloadToAcl2(cbor, size);
+    if (NULL == acl)
+    {
+        OIC_LOG(ERROR, TAG, "Can't parse CBOR payload");
+        goto exit;
+    }
+
+    result = InstallNewACL2(acl);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "Can't update ACL resource");
+    }
+
+exit:
+    //can't delete acl because aces was added to gAcl
+    OICFree(cbor);
+    return result;
+}
+
+OCStackResult OCCloudAclIndividualGetInfo(void* ctx,
+                                          const char *aclId,
+                                          const OCDevAddr *endPoint,
+                                          OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH]  = { 0 };
+
+    VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleAclGetInfoResponse, NULL);
+
+    return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclIndividualUpdateAce(void* ctx,
+                                            const char *aclId,
+                                            const cloudAce_t *aces,
+                                            const OCDevAddr *endPoint,
+                                            OCCloudResponseCB callback)
+{
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+    char uri[MAX_URI_LENGTH]  = { 0 };
+
+    int i = 0, j = 0;
+
+    OCRepPayload **helperPayload  = NULL;
+    OCRepPayload **helperPayload2 = NULL;
+
+    VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(aces, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
+
+    OCRepPayload *payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for payload");
+        goto no_memory;
+    }
+
+    int acllist_count = 0;
+    if (aces)
+    {
+        cloudAce_t *ace = (cloudAce_t *)&aces[acllist_count++];
+        while (ace->next)
+        {
+            ace = ace->next;
+            acllist_count++;
+        }
+    }
+
+    helperPayload = OICCalloc(acllist_count, sizeof(OCRepPayload *));
+    if (!helperPayload)
+    {
+        OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload");
+        goto no_memory;
+    }
+
+    for (int i = 0; i < acllist_count; i++)
+    {
+        OCRepPayload *payload = OCRepPayloadCreate();
+        if (!payload)
+        {
+            OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload[i]");
+            goto no_memory;
+        }
+        helperPayload[i] = payload;
+
+        const cloudAce_t *ace = &aces[i];
+
+        OCRepPayloadSetPropString(payload, OC_RSRVD_ACE_ID, ace->aceId);
+        OCRepPayloadSetPropString(payload, OC_RSRVD_SUBJECT_UUID, (const char *)ace->subjectuuid.id);
+        OCRepPayloadSetPropInt(payload, OC_RSRVD_SUBJECT_TYPE, ace->stype);
+        OCRepPayloadSetPropInt(payload, OC_RSRVD_PERMISSION_MASK, ace->permission);
+
+        int reslist_count = 0;
+        if (ace->resources)
+        {
+            OicSecRsrc_t *res = &ace->resources[reslist_count++];
+            while (res->next)
+            {
+                res = res->next;
+                reslist_count++;
+            }
+        }
+
+        helperPayload2 = OICCalloc(reslist_count, sizeof(OCRepPayload *));
+        if (!helperPayload2)
+        {
+            goto no_memory;
+        }
+
+        for (int j = 0; j < reslist_count; j++)
+        {
+            OCRepPayload *payload = OCRepPayloadCreate();
+            if (!payload)
+            {
+                OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for payload");
+                goto no_memory;
+            }
+            helperPayload2[j] = payload;
+
+            const OicSecRsrc_t *res = &ace->resources[j];
+
+            OCRepPayloadSetPropString(payload, OC_RSRVD_HREF, res->href);
+
+            dimensions[0] = res->typeLen;
+            OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE,
+                                       (const char **)res->types, dimensions);
+
+            dimensions[0] = res->interfaceLen;
+            OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE,
+                                       (const char **)res->interfaces, dimensions);
+        }
+        dimensions[0] = reslist_count;
+        OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_RESOURCES,
+                (const OCRepPayload **)helperPayload2, dimensions);
+    }
+    dimensions[0] = acllist_count;
+    OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_ACCESS_CONTROL_LIST,
+            (const OCRepPayload **)helperPayload, dimensions);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    OIC_LOG(DEBUG, TAG, "Next payload created:");
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+no_memory:
+    if (helperPayload2)
+    {
+        for (int k = 0; k < j; k++) OCRepPayloadDestroy(helperPayload2[k]);
+        OICFree(helperPayload2);
+    }
+    if (helperPayload)
+    {
+        for (int k = 0; k < i; k++) OCRepPayloadDestroy(helperPayload[k]);
+        OICFree(helperPayload);
+    }
+    OCRepPayloadDestroy(payload);
+    return OC_STACK_NO_MEMORY;
+}
+
+OCStackResult OCCloudAclIndividualDelete(void* ctx,
+                                         const char *aclId,
+                                         const OCDevAddr *endPoint,
+                                         OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH]  = { 0 };
+
+    VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
diff --git a/resource/csdk/security/provisioning/src/cloud/aclinvite.c b/resource/csdk/security/provisioning/src/cloud/aclinvite.c
new file mode 100644 (file)
index 0000000..9b77374
--- /dev/null
@@ -0,0 +1,360 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "occloudprovisioning.h"
+#include "utils.h"
+
+#include "oic_malloc.h"
+#include "logger.h"
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "pmutility.h"
+#include "cacommonutil.h"
+
+#define TAG "CLOUD-ACL-INVITE"
+
+/**
+ * This helper function parses "name" : { "gid":[], "mid":[] } payload
+ *
+ * @param[in] payload     received payload
+ * @param[in] name        property name
+ * @param[out] out        string array pair to fill
+ * @return  OCStackResult application result
+ */
+static OCStackResult parseInvitePayload(const OCRepPayload *payload, const char *name, stringArrayPair_t *out)
+{
+    OCStackResult result = OC_STACK_NO_MEMORY;
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+    OCRepPayload **heplerPayload  = NULL;
+    size_t i = 0;
+
+    if (!OCRepPayloadGetPropObjectArray(payload, name, &heplerPayload, dimensions))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get: %s", name);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    int count = calcDimTotal(dimensions);
+
+    stringArray_t *gidlist = &out->gidlist;
+    stringArray_t *midlist = &out->midlist;
+
+    gidlist->length = count;
+    midlist->length = count;
+
+    gidlist->array = OICCalloc(gidlist->length, sizeof(char *));
+    if (NULL == gidlist->array)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate gidlist->array");
+        goto exit;
+    }
+
+    midlist->array = OICCalloc(midlist->length, sizeof(char *));
+    if (NULL == midlist->array)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate midlist->array");
+        goto exit;
+    }
+
+    for (i = 0; i < gidlist->length; i++)
+    {
+        const OCRepPayload *payload = heplerPayload[i];
+
+        if (!OCRepPayloadGetPropString(payload, OC_RSRVD_GROUP_ID, &gidlist->array[i]))
+        {
+            OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_GROUP_ID);
+            result = OC_STACK_MALFORMED_RESPONSE;
+            goto exit;
+        }
+
+        if (!OCRepPayloadGetPropString(payload, OC_RSRVD_MEMBER_ID, &midlist->array[i]))
+        {
+            OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_MEMBER_ID);
+            result = OC_STACK_MALFORMED_RESPONSE;
+            goto exit;
+        }
+        OCRepPayloadDestroy(heplerPayload[i]);
+    }
+
+    result = OC_STACK_OK;
+
+exit:
+    if (result != OC_STACK_OK)
+    {
+        clearStringArray(gidlist);
+        clearStringArray(midlist);
+
+        for (size_t k = i; k < gidlist->length; k++)
+        {
+            OCRepPayloadDestroy(heplerPayload[i]);
+        }
+    }
+    OICFree(heplerPayload);
+    return result;
+}
+
+/**
+ * ACL get invitation request received data handler
+ *
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult handleAclGetInvitationResponse(void *ctx, void **data, OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OCStackResult result = OC_STACK_OK;
+
+    if (NULL == response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    inviteResponse_t *answer = OICCalloc(1, sizeof(inviteResponse_t));
+    if (NULL == answer)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate answer");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    const OCRepPayload *payload = (const OCRepPayload *)response->payload;
+
+    result = parseInvitePayload(payload, OC_RSRVD_INVITE, &answer->invite);
+    if (result != OC_STACK_OK)
+    {
+        goto exit;
+    }
+
+    result = parseInvitePayload(payload, OC_RSRVD_INVITED, &answer->invited);
+    if (result != OC_STACK_OK)
+    {
+        goto exit;
+    }
+
+    *data = answer;
+
+exit:
+    if (result != OC_STACK_OK)
+    {
+        OICFree(answer);
+    }
+    return result;
+}
+
+/**
+ * ACL policy check request received data handler
+ *
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult handleAclPolicyCheckResponse(void *ctx, void **data, OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+
+    if (NULL == response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char *gp = NULL;
+
+    if (!OCRepPayloadGetPropString((const OCRepPayload *)response->payload, OC_RSRVD_GROUP_PERMISSION, &gp))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_GROUP_PERMISSION);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    *data = gp;
+    return OC_STACK_OK;
+}
+
+OCStackResult OCCloudAclInviteUser(void* ctx,
+                                   const char *userId,
+                                   const stringArray_t *groupIds,
+                                   const stringArray_t *memberIds,
+                                   const OCDevAddr *endPoint,
+                                   OCCloudResponseCB callback)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    char uri[MAX_URI_LENGTH] = { 0 };
+    size_t i = 0;
+
+    VERIFY_NON_NULL_RET(groupIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(memberIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    if (groupIds->length != memberIds->length)
+    {
+        OIC_LOG(ERROR, TAG, "members and groups lists should have the same length!!!");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    OCRepPayload *payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCRepPayload **heplerPayload = OICCalloc(groupIds->length, sizeof(OCRepPayload *));
+
+    for (i = 0; i < groupIds->length; i++)
+    {
+        heplerPayload[i] = OCRepPayloadCreate();
+        if (!heplerPayload[i])
+        {
+            goto no_memory;
+        }
+        OCRepPayloadSetPropString(heplerPayload[i], OC_RSRVD_GROUP_ID, groupIds->array[i]);
+        OCRepPayloadSetPropString(heplerPayload[i], OC_RSRVD_MEMBER_ID, memberIds->array[i]);
+    }
+
+    //add next fields if they were filled
+    if (userId) OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, userId);
+
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = {groupIds->length, 0, 0};
+    OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_INVITE,
+            (const struct OCRepPayload **)heplerPayload, dimensions);
+
+    return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+no_memory:
+    OCRepPayloadDestroy(payload);
+    for (size_t k = 0; k < i; k++)
+    {
+        OCRepPayloadDestroy(heplerPayload[k]);
+    }
+    OCRepPayloadDestroy(*heplerPayload);
+    return result;
+}
+
+OCStackResult OCCloudAclGetInvitation(void* ctx,
+                                      const char *userId,
+                                      const OCDevAddr *endPoint,
+                                      OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
+
+    if (userId)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, MAX_URI_LENGTH -len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
+    }
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleAclGetInvitationResponse, NULL);
+
+    return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclDeleteInvitation(void* ctx,
+                                         const char *userId,
+                                         const char *groupId,
+                                         const OCDevAddr *endPoint,
+                                         OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
+
+    if (userId)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
+    }
+
+    size_t len = strlen(uri);
+    snprintf(uri + len, MAX_URI_LENGTH - len, "%c%s=%s", userId?'&':'?', OC_RSRVD_GROUP_ID, groupId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclCancelInvitation(void* ctx,
+                                         const char *userId,
+                                         const char *groupId,
+                                         const char *memberId,
+                                         const OCDevAddr *endPoint,
+                                         OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+    size_t len = 0 ;
+
+    VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(memberId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
+
+    if (userId)
+    {
+        size_t len = strlen(uri);
+        snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
+    }
+
+    len = strlen(uri);
+    snprintf(uri + len, MAX_URI_LENGTH - len, "%c%s=%s", userId?'&':'?', OC_RSRVD_GROUP_ID, groupId);
+    len = strlen(uri);
+    snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_MEMBER_ID, memberId);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudAclPolicyCheck(void* ctx,
+                                    const char *subjectId,
+                                    const char *deviceId,
+                                    const char *method,
+                                    const char *user_uri,
+                                    const OCDevAddr *endPoint,
+                                    OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+    size_t len = 0;
+
+    VERIFY_NON_NULL_RET(subjectId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(method, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(user_uri, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_ACL_VERIFY_URL);
+
+    len = strlen(uri);
+    snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_SUBJECT_ID, subjectId);
+    len = strlen(uri);
+    snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_DEVICE_ID, deviceId);
+    len = strlen(uri);
+    snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_REQUEST_METHOD, method);
+    len = strlen(uri);
+    snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_REQUEST_URI, user_uri);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleAclPolicyCheckResponse, NULL);
+
+    return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
diff --git a/resource/csdk/security/provisioning/src/cloud/crl.c b/resource/csdk/security/provisioning/src/cloud/crl.c
new file mode 100644 (file)
index 0000000..088b1d5
--- /dev/null
@@ -0,0 +1,170 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "utils.h"
+
+#include "logger.h"
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "pmutility.h"
+#include "oic_malloc.h"
+#include "crlresource.h"
+#include "ocpayloadcbor.h"
+#include "payload_logging.h"
+#include "cacommonutil.h"
+
+#define TAG "CLOUD-CRL"
+
+/**
+ * CRL GET request received data handler
+ *
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult handleCrlGetResponse(void *ctx, void **data, OCClientResponse *response)
+{
+    OCStackResult result = OC_STACK_OK;
+    OicSecCrl_t *crl = NULL;
+
+    OC_UNUSED(ctx);
+    OC_UNUSED(data);
+
+    if (NULL == response->payload)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NULL payload\n");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCPayloadType type = response->payload->type;
+
+    if (type != PAYLOAD_TYPE_SECURITY)
+    {
+        OIC_LOG(ERROR, TAG, "Receive NOT security payload, can't parse it!\n");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCSecurityPayload *payload = (OCSecurityPayload *)response->payload;
+
+    result = CBORPayloadToCrl(payload->securityData, payload->payloadSize, &crl);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "Can't convert cbor to Crl");
+        goto exit;
+    }
+
+    result = UpdateCRLResource(crl);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "Can't update Crl resource");
+    }
+
+exit:
+    DeleteCrl(crl);
+    return result;
+}
+
+OCStackResult OCCloudGetCRL(void* ctx,
+                            const OCDevAddr *endPoint,
+                            OCCloudResponseCB callback)
+{
+    char uri[MAX_URI_LENGTH] = { 0 };
+    char *lastUpdate = NULL;
+
+    getLastUpdateFromDB(&lastUpdate);
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port,
+            OC_RSRVD_PROV_CRL_URL, OC_RSRVD_LAST_UPDATE, lastUpdate);
+
+    OICFree(lastUpdate);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, handleCrlGetResponse, NULL);
+
+    return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+OCStackResult OCCloudPostCRL(void* ctx,
+                             const char *thisUpdate,
+                             const char *nextUpdate,
+                             const OCByteString *crl,
+                             const stringArray_t *serialNumbers,
+                             const OCDevAddr *endPoint,
+                             OCCloudResponseCB callback)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    char uri[MAX_URI_LENGTH] = { 0 };
+    OCRepPayload *payload = NULL;
+    OCSecurityPayload *secPayload = NULL;
+    uint8_t *cbor = NULL;
+    size_t cbor_len = 0;
+    OicSecKey_t crl1;
+
+    VERIFY_NON_NULL_RET(thisUpdate, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(nextUpdate, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
+
+    if (crl)
+    {
+        crl1.data = crl->bytes;
+        crl1.len  = crl->len;
+        crl1.encoding = OIC_ENCODING_DER;
+    }
+
+    snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
+            endPoint->addr, endPoint->port, OC_RSRVD_PROV_CRL_URL);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, NULL, NULL);
+
+    payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate payload");
+        goto exit;
+    }
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_THIS_UPDATE, thisUpdate);
+    OCRepPayloadSetPropString(payload, OC_RSRVD_NEXT_UPDATE, nextUpdate);
+
+    //add next fields if they were filled
+    if (serialNumbers)
+    {
+        size_t dimensions[MAX_REP_ARRAY_DEPTH] = {serialNumbers->length, 0 ,0};
+        OCRepPayloadSetStringArray(payload, OC_RSRVD_SERIAL_NUMBERS,
+                                   (const char**)serialNumbers->array, dimensions);
+
+    }
+    if (crl) OCRepPayloadSetPropPubDataType(payload, OC_RSRVD_CRL, &crl1);
+
+    OIC_LOG(DEBUG, TAG, "Next payload created:");
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
+
+    secPayload = OICCalloc(1, sizeof(OCSecurityPayload));
+    if (!secPayload)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate secPayload");
+        goto exit;
+    }
+
+    result = OCConvertPayload((OCPayload *)payload, &cbor, &cbor_len);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "Can't convert OCPayload to cbor");
+        OICFree(secPayload);
+        goto exit;
+    }
+
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = cbor;
+    secPayload->payloadSize = cbor_len;
+
+    result = OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)secPayload,
+                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
+exit:
+    OCPayloadDestroy((OCPayload *)payload);
+    return result;
+}
diff --git a/resource/csdk/security/provisioning/src/cloud/csr.c b/resource/csdk/security/provisioning/src/cloud/csr.c
new file mode 100644 (file)
index 0000000..f95328d
--- /dev/null
@@ -0,0 +1,491 @@
+#include "utils.h"
+
+#include "logger.h"
+#include <stddef.h>
+#include <string.h>
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "cacommonutil.h"
+
+#include "ocpayload.h"
+#include "payload_logging.h"
+#include "doxmresource.h"
+#include "pmutility.h"
+#include "secureresourceprovider.h"
+
+// headers required for mbed TLS
+#include "mbedtls/platform.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/pkcs12.h"
+#include "mbedtls/ssl_internal.h"
+#include "mbedtls/x509_csr.h"
+
+#ifndef NDEBUG
+#include "mbedtls/debug.h"
+#include "mbedtls/version.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#define TAG "CLOUD-CSR"
+
+//TODO: is it required in CSR response?
+static OCByteString privateKey = {0, 0};
+
+#define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
+
+#define MAX_STRING_LEN 254
+
+/**
+ * @def SEED
+ * @brief Seed for initialization RNG
+ */
+
+#define SEED "IOTIVITY_RND"
+
+typedef struct
+{
+    char *subject;
+    char *prKey;
+    size_t prKeyLen;
+    char *pubKey;
+    size_t pubKeyLen;
+} SignCred_t;
+
+/**
+ * Make CSR subject like:
+ * Subject: C=KR, O=Samsung, OU=OCF Device, CN=uuid:1234567890
+ * @param[in] subj              the subject
+ */
+static void CSRMakeSubject(char *subject, const char *countryCode, const char *organisation,
+                    const char *organizationalUnitName, const char *deviceId)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (!deviceId)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: The device id is NULL",__func__);
+        return;
+    }
+    snprintf(subject, MAX_STRING_LEN, "C=%s, O=%s, OU=%s, CN=uuid:%s", countryCode, organisation, organizationalUnitName, deviceId);
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+}
+/**
+ * Generates elliptic keypair.
+ *
+ * @param[out]  pk    mbedtls public key container
+ *
+ * @return  0 on success or -1 on error
+ */
+static int ecdsaGenKeypair(mbedtls_pk_context * pk)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctr_drbg;
+
+    VERIFY_NON_NULL_RET(pk, TAG, "Param pk is NULL", -1);
+
+    // Entropy seeding
+#ifdef __unix__
+    unsigned char seed[sizeof(SEED)] = {0};
+    int urandomFd = -2;
+    urandomFd = open("/dev/urandom", O_RDONLY);
+    if(urandomFd == -1)
+    {
+        OIC_LOG(ERROR, TAG, "Fails open /dev/urandom!");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    if(0 > read(urandomFd, seed, sizeof(seed)))
+    {
+        OIC_LOG(ERROR, TAG, "Fails read from /dev/urandom!");
+        close(urandomFd);
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    close(urandomFd);
+
+#else
+    unsigned char * seed = (unsigned char*) SEED;
+#endif
+    // Initialize and seed DRBG context
+    mbedtls_ctr_drbg_init(&ctr_drbg);
+    mbedtls_entropy_init(&entropy);
+    if (0 != mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
+                                   &entropy, seed, sizeof(SEED)))
+    {
+        OIC_LOG(ERROR, TAG, "Seed initialization failed!");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF);
+    // Initialize l context
+    mbedtls_pk_init(pk);
+    if (0 > mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)))
+    {
+        OIC_LOG(ERROR, TAG, "mbedtls_pk_info_from_type error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    if (0 > mbedtls_ecp_group_load(&mbedtls_pk_ec(*pk)->grp, MBEDTLS_ECP_DP_SECP256R1))
+    {
+        OIC_LOG(ERROR, TAG, "mbedtls_ecp_group_load error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    if (0 > mbedtls_ecp_gen_keypair(&mbedtls_pk_ec(*pk)->grp,
+                                    &mbedtls_pk_ec(*pk)->d,
+                                    &mbedtls_pk_ec(*pk)->Q,
+                                    mbedtls_ctr_drbg_random, &ctr_drbg))
+    {
+        OIC_LOG(ERROR, TAG, "mbedtls_ecp_gen_keypair error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+    return 0;
+}
+
+
+
+/**
+ * Generates keypair and certificate signing request.
+ *
+ * @param[in]  subjectName    CSR Subject names should contain
+ * a comma-separated list of OID types and values:
+ * e.g. "C=UA,O=ABC,CN=uuid:32323232-3232-3232-3232-323232323232"
+ * @param[out] prKey          private key in DER
+ * @param[out] prKeyLen       private key buffer length
+ * @param[out] pubKey         public key in DER
+ * @param[out] pubKeyLen      public key buffer length
+ * @param[out] CSR            certificate signing request in DER
+ * @param[out] CSRLen         certificate signing request buffer length
+ *
+ * @return  0 on success or -1 on error
+ */
+static int GenerateCSR(char *subject, OCByteString *csr)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(subject, TAG, "Param subject is NULL", -1);
+    VERIFY_NON_NULL_RET(csr, TAG, "Param csr is NULL", -1);
+
+    int ret = 0;
+    int bufsize = 1024;
+    unsigned char * buf = NULL;
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctr_drbg;
+    mbedtls_pk_context * key = NULL;
+    mbedtls_x509write_csr req;
+
+    // Initialize keypair context
+    key = (mbedtls_pk_context *)OICMalloc(sizeof(mbedtls_pk_context));
+    if (NULL == key)
+    {
+        OIC_LOG_V(ERROR, TAG, "OICMalloc returned NULL on key allocation");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    // Generate keypair
+    if (0 > ecdsaGenKeypair(key))
+    {
+        OIC_LOG(ERROR, TAG, "ecdsaGenKeypair error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+
+    // Initialize CSR context
+    mbedtls_x509write_csr_init(&req);
+    // Set up MD algorithm, key and subject to CSR
+    mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256);
+    mbedtls_x509write_csr_set_key(&req, key);
+    if (0 > mbedtls_x509write_csr_set_subject_name(&req, subject))
+    {
+        OIC_LOG(ERROR, TAG, "mbedtls_x509write_csr_set_subject_name error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+
+    // Entropy seeding
+#ifdef __unix__
+    unsigned char seed[sizeof(SEED)] = {0};
+    int urandomFd = -2;
+    urandomFd = open("/dev/urandom", O_RDONLY);
+    if(urandomFd == -1)
+    {
+        OIC_LOG(ERROR, TAG, "Fails open /dev/urandom!");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    if(0 > read(urandomFd, seed, sizeof(seed)))
+    {
+        OIC_LOG(ERROR, TAG, "Fails read from /dev/urandom!");
+        close(urandomFd);
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    close(urandomFd);
+
+#else
+    unsigned char * seed = (unsigned char *) SEED;
+#endif
+    // Initialize and seed DRBG context
+    mbedtls_ctr_drbg_init(&ctr_drbg);
+    mbedtls_entropy_init(&entropy);
+    if (0 != mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
+                                   &entropy, seed, sizeof(SEED)))
+    {
+        OIC_LOG(ERROR, TAG, "Seed initialization failed!");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF);
+
+    // Create CSR
+    buf = (unsigned char *)OICMalloc(bufsize * sizeof(unsigned char));
+    if (NULL == buf)
+    {
+        OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on buf allocation");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    ret = mbedtls_x509write_csr_der(&req, buf, bufsize,
+                                    mbedtls_ctr_drbg_random, &ctr_drbg);
+    if (ret < 0)
+    {
+        OIC_LOG(ERROR, TAG, "mbedtls_x509write_csr_der error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+
+    // CSR to output
+    csr->bytes = (uint8_t *)OICMalloc(ret * sizeof(uint8_t));
+    if (NULL == csr->bytes)
+    {
+        OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on csr allocation");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    memcpy(csr->bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
+    csr->len = ret;
+    // Private key to output
+    ret = mbedtls_pk_write_key_der(key, buf, bufsize);
+    if (ret < 0)
+    {
+        OIC_LOG(ERROR, TAG, "mbedtls_pk_write_key_der error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    privateKey.bytes = (uint8_t *)OICMalloc(ret * sizeof(char));
+    if (NULL == privateKey.bytes)
+    {
+        OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on privateKey.bytes allocation");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    memcpy(privateKey.bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
+    privateKey.len = ret;
+    // Public key to output
+    ret = mbedtls_pk_write_pubkey_der(key, buf, bufsize);
+    if (ret < 0)
+    {
+        OIC_LOG(ERROR, TAG, "mbedtls_pk_write_pubkey_der error");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    //leave this, may be public key will be required in future
+    OCByteString publicKey;
+    publicKey.bytes = (uint8_t *)OICMalloc(ret * sizeof(char));
+    if (NULL == publicKey.bytes)
+    {
+        OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on pubKey allocation");
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        return -1;
+    }
+    memcpy(publicKey.bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
+    publicKey.len = ret;
+    OICFree(publicKey.bytes);
+
+    mbedtls_entropy_free(&entropy);
+    mbedtls_ctr_drbg_free(&ctr_drbg);
+    mbedtls_x509write_csr_free(&req);
+    OICFree(key);
+
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+    return 0;
+}
+
+/**
+ * Cloud CSR Sign response handler
+
+ * @param[in] ctx       context
+ * @param[out] data     data required to external application
+ * @param[in] response  peer response
+ * @return  OCStackResult application result
+ */
+static OCStackResult HandleCertificateIssueRequest(void *ctx, void **data, OCClientResponse *response)
+{
+    OCStackResult result = OC_STACK_OK;
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    OC_UNUSED(ctx);
+    OC_UNUSED(data);
+
+    if (!response)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: Client response is null",__func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if (response->result < 4 && response->payload)
+    {
+        OIC_LOG_V(ERROR, TAG, "CSR sign error: result: %d, payload null: %s",
+                  response->result, response->payload ? "no" : "yes");
+        OIC_LOG_PAYLOAD(DEBUG, response->payload);
+        return OC_STACK_ERROR;
+    }
+
+    char *deviceId = 0;
+
+    if (!OCRepPayloadGetPropString((OCRepPayload *)response->payload,
+                                   OC_RSRVD_DEVICE_ID, &deviceId))
+    {
+        OIC_LOG(ERROR, TAG, "Can't get: Device Id");
+        result = OC_STACK_ERROR;
+    }
+
+    OicSecKey_t cert;
+    if (!OCRepPayloadGetPropPubDataType((OCRepPayload *)response->payload,
+                                   OC_RSRVD_CERT, &cert))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_CERT);
+        result = OC_STACK_ERROR;
+    }
+    else
+    {
+        OicSecKey_t key =
+        {
+            privateKey.bytes,
+            privateKey.len,
+            OIC_ENCODING_DER
+        };
+
+        OicSecCert_t cert1 =
+        {
+            cert.data,
+            cert.len,
+        };
+
+        uint16_t credId;
+        result = SRPSaveOwnCertChain(&cert1, &key, &credId);
+        if (result != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG, "Cann't add cert");
+        }
+    }
+
+    //get cacert
+    OicSecKey_t caCert;
+    if (!OCRepPayloadGetPropPubDataType((OCRepPayload *)response->payload,
+                                   OC_RSRVD_CACERT, &caCert))
+    {
+        OIC_LOG_V(ERROR, TAG, "Cann't get: %s", OC_RSRVD_CACERT);
+        result = OC_STACK_ERROR;
+    }
+    else
+    {
+        uint16_t credId;
+        result = SRPSaveTrustCertChain(caCert.data, caCert.len, caCert.encoding, &credId);
+        if (result != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG, "Can't insert CA cert");
+        }
+    }
+
+    OICFree(privateKey.bytes);
+    privateKey.bytes = NULL;
+    privateKey.len   = 0;
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+
+    return result;
+}
+
+/**
+ * Certificate-Issue request function
+ *
+ * @param[in] endPoint          cloud host and port
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudCertificateIssueRequest(void* ctx,
+                                             const OCDevAddr *endPoint,
+                                             OCCloudResponseCB callback)
+{
+    OCStackResult ret = OC_STACK_OK;
+
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (NULL == endPoint)
+    {
+        OIC_LOG(ERROR, TAG, "Input parameter endpoint is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char *deviceId = getDeviceId();
+
+    char subject[MAX_STRING_LEN] = { 0 };
+    CSRMakeSubject(subject, "KR", "Samsung", "OCF Device", deviceId);
+
+    OIC_LOG_V(DEBUG, TAG, "Certificate Request subject: %s", subject);
+
+    OCByteString request;
+    if (0 != GenerateCSR(subject, &request))
+    {
+        OIC_LOG(ERROR, TAG, "Cann't get the sertificate request");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    OIC_LOG(DEBUG, TAG, "Certificate Request:");
+    OIC_LOG_BUFFER(DEBUG, TAG, request.bytes, request.len);
+
+    OIC_LOG(DEBUG, TAG, "Private Key:");
+    OIC_LOG_BUFFER(DEBUG, TAG, privateKey.bytes, privateKey.len);
+
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
+
+    OicSecKey_t csr = {.data = request.bytes, .len = request.len, .encoding = OIC_ENCODING_DER};
+
+    OCRepPayloadSetPropPubDataType(payload, OC_RSRVD_CSR, &csr);
+
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
+
+    char uri[MAX_URI_QUERY] = { 0 };
+    snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
+             endPoint->addr, endPoint->port,
+             OC_RSRVD_PROV_CERT_URI);
+
+    OCCallbackData cbData;
+    fillCallbackData(&cbData, ctx, callback, HandleCertificateIssueRequest, NULL);
+
+    ret = OCDoResource(NULL, OC_REST_POST, uri, NULL,
+                       (OCPayload *)payload,
+                       CT_ADAPTER_TCP,
+                       OC_LOW_QOS, &cbData, NULL, 0);
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+exit:
+    OICFree(request.bytes);
+    return ret;
+}
diff --git a/resource/csdk/security/provisioning/src/cloud/utils.c b/resource/csdk/security/provisioning/src/cloud/utils.c
new file mode 100644 (file)
index 0000000..2b376a7
--- /dev/null
@@ -0,0 +1,163 @@
+#include "utils.h"
+
+#include "logger.h"
+#include "payload_logging.h"
+#include "oic_malloc.h"
+#include "doxmresource.h"
+#include "srmutility.h"
+#include "pmutility.h"
+
+#define TAG "CLOUD-UTILS"
+
+typedef struct {
+    void *ctx;
+    OCCloudResponseCB cb;
+    UserFunctionCB fn;
+    void *params;
+}ContextInfo_t;
+
+char *DEFAULT_QUERY  = COAP_TCP_QUERY;
+char *DEFAULT_PREFIX = COAP_TCP_PREFIX;
+
+/**
+ * This function sets required CoAP prefix depending on
+ * secure or non-secure connection
+ *
+ * @param[in] secure   secure flag
+ */
+void setCoapPrefix(bool secure)
+{
+    if (secure)
+    {
+        DEFAULT_QUERY  = COAPS_TCP_QUERY;
+        DEFAULT_PREFIX = COAPS_TCP_PREFIX;
+    }
+    else
+    {
+        DEFAULT_QUERY  = COAP_TCP_QUERY;
+        DEFAULT_PREFIX = COAP_TCP_PREFIX;
+    }
+}
+
+/**
+ * This hepler function handles response from each request
+ * During execution it calls proper callbacks
+ *
+ * @param[in] ctx             context
+ * @param[in] handle          handle
+ * @param[in] clientResponse  response from peer
+ */
+static OCStackApplicationResult handleResponse(void *ctx,
+                                              OCDoHandle handle,
+                                              OCClientResponse *clientResponse)
+{
+    OC_UNUSED(handle);
+
+    if (NULL == clientResponse)
+    {
+        OIC_LOG_V(ERROR, TAG, "Received null response from client");
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Received callback with response code: %d", clientResponse->result);
+
+    if (clientResponse->payload)
+    {
+        OIC_LOG(DEBUG, TAG, "Payload received:");
+        OIC_LOG_PAYLOAD(DEBUG, clientResponse->payload);
+    }
+
+    if (ctx)
+    {
+        OCStackResult result = clientResponse->result;
+        void *data = NULL;
+
+        ContextInfo_t *info = (ContextInfo_t *)ctx;
+
+        if (info->fn)
+        {
+            result = ((UserFunctionCB)info->fn)(info->params, &data, clientResponse);
+        }
+
+        if (info->cb)
+        {
+            ((OCCloudResponseCB)info->cb)(info->ctx, result, data);
+        }
+    }
+
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+static void deleteContextInfo(void *info)
+{
+    OICFree(info);
+}
+
+void fillCallbackData(OCCallbackData *cbData, void *ctx, OCCloudResponseCB cb,
+                                              UserFunctionCB fn, void *params)
+{
+    memset(cbData, 0, sizeof(OCCallbackData));
+
+    ContextInfo_t *info = OICCalloc(1, sizeof(ContextInfo_t));
+    if (!info)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate memory for info");
+        return;
+    }
+
+    info->ctx = ctx;
+    info->cb  = cb;
+    info->fn  = fn;
+    info->params = params;
+
+    cbData->cb = handleResponse;
+    cbData->cd = deleteContextInfo;
+    cbData->context = info;
+}
+
+char * getDeviceId()
+{
+    char *deviceId = NULL;
+    OicUuid_t uuid;
+
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    memset(&uuid, 0, sizeof(uuid));
+    if (OC_STACK_OK != GetDoxmDeviceID(&uuid))
+    {
+        OIC_LOG(ERROR, TAG, "Cann't get the device id(GetDoxmDeviceID)");
+        goto exit;
+    }
+
+    if (OC_STACK_OK != ConvertUuidToStr(&uuid, &deviceId))
+    {
+        OIC_LOG(ERROR, TAG, "Cann't get the device id(ConvertUuidToStr)");
+        goto exit;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "device Id: %s", deviceId);
+exit:
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+    return deviceId;
+}
+
+/**
+ * Clear previously filled array of strings
+ *
+ * @param[out] list           array of strings structure to clear
+ * @param[in] count           elements count
+ */
+void clearStringArray(stringArray_t *list)
+{
+    if (!list || !list->array)
+    {
+        return;
+    }
+
+    for (size_t i = 0; i < list->length; i++)
+    {
+        OICFree(list->array[i]);
+    }
+    OICFree(list->array);
+}
+
index fcf6536..8bcfebd 100644 (file)
@@ -473,7 +473,8 @@ OCStackResult SRPProvisionCRL(void *ctx, const OCProvisionDev_t *selectedDeviceI
     }
 
     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
-    OCStackResult res = CrlToCBORPayload(crl, &secPayload->securityData, &secPayload->payloadSize);
+    OCStackResult res;
+    res = CrlToCBORPayload(crl, &secPayload->securityData, &secPayload->payloadSize, NULL);
     if((OC_STACK_OK != res) && (NULL == secPayload->securityData))
     {
         OICFree(secPayload);
@@ -773,6 +774,60 @@ OCStackResult SRPSaveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
 
     return res;
 }
+
+
+OCStackResult SRPSaveOwnCertChain(OicSecCert_t * cert, OicSecKey_t * key, uint16_t *credId)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    VERIFY_NON_NULL(TAG, cert, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, cert->data, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, key, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, key->data, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
+
+    OCStackResult res = OC_STACK_ERROR;
+
+    OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
+    VERIFY_NON_NULL(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
+
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (OC_STACK_OK != GetDoxmDeviceID(&cred->subject))
+    {
+        OIC_LOG(ERROR, TAG, "Cann't get the device id(GetDoxmDeviceID)");
+    }
+
+    cred->credUsage= (char *)OICCalloc(1, strlen(PRIMARY_CERT)+1 );
+    VERIFY_NON_NULL(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
+    OICStrcpy(cred->credUsage, strlen(PRIMARY_CERT) + 1, PRIMARY_CERT) ;
+
+    cred->credType = SIGNED_ASYMMETRIC_KEY;
+
+    OicSecCert_t *publicData = &cred->publicData;
+    publicData->data = (uint8_t *)OICCalloc(1, cert->len);
+    VERIFY_NON_NULL(TAG, publicData->data, ERROR, OC_STACK_NO_MEMORY);
+    memcpy(publicData->data, cert->data, cert->len);
+    publicData->len = cert->len;
+
+    OicSecKey_t *privateData = &cred->privateData;
+    privateData->data = (uint8_t *)OICCalloc(1, key->len);
+    VERIFY_NON_NULL(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY);
+    memcpy(privateData->data, key->data, key->len);
+    privateData->len = key->len;
+    privateData->encoding = key->encoding;
+
+    res = AddCredential(cred);
+    if(res != OC_STACK_OK)
+    {
+        DeleteCredList(cred);
+        return res;
+    }
+    *credId = cred->credId;
+
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+
+    return res;
+}
 #endif // __WITH_X509__ || __WITH_TLS__
 
 OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
index 450123f..1d6cfd9 100644 (file)
@@ -42,6 +42,7 @@
 #include "resourcemanager.h"
 #include "srmutility.h"
 #include "psinterface.h"
+#include "ocpayloadcbor.h"
 
 #include "security_internals.h"
 
@@ -636,6 +637,312 @@ exit:
 
 // This function converts CBOR format to ACL data.
 // Caller needs to invoke 'free' when done using
+// It parses { "aclist" : [ { ... } ] } instead of { "aclist" : { "aces" : [ ] } }
+OicSecAcl_t* CBORPayloadToAcl2(const uint8_t *cborPayload, const size_t size)
+{
+    if (NULL == cborPayload || 0 == size)
+    {
+        return NULL;
+    }
+    OCStackResult ret = OC_STACK_ERROR;
+    CborValue aclCbor = { .parser = NULL };
+    CborParser parser = { .end = NULL };
+    CborError cborFindResult = CborNoError;
+    cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor);
+
+    OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
+
+    // Enter ACL Map
+    CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
+    cborFindResult = cbor_value_enter_container(&aclCbor, &aclMap);
+    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
+
+    while (cbor_value_is_valid(&aclMap))
+    {
+        char* tagName = NULL;
+        size_t len = 0;
+        CborType type = cbor_value_get_type(&aclMap);
+        if (type == CborTextStringType)
+        {
+            cborFindResult = cbor_value_dup_text_string(&aclMap, &tagName, &len, NULL);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACL Map.");
+            cborFindResult = cbor_value_advance(&aclMap);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACL Map.");
+        }
+        if(tagName)
+        {
+            if (strcmp(tagName, OIC_JSON_ACLIST_NAME)  == 0)
+            {
+                // Enter ACES Array
+                CborValue acesArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
+                cborFindResult = cbor_value_enter_container(&aclMap, &acesArray);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACES Array.");
+
+                int acesCount = 0;
+                while (cbor_value_is_valid(&acesArray))
+                {
+                    acesCount++;
+                    CborValue aceMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
+                    cborFindResult = cbor_value_enter_container(&acesArray, &aceMap);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACE Map.");
+
+                    OicSecAce_t *ace = NULL;
+                    ace = (OicSecAce_t *) OICCalloc(1, sizeof(OicSecAce_t));
+                    VERIFY_NON_NULL(TAG, ace, ERROR);
+                    LL_APPEND(acl->aces, ace);
+
+                    VERIFY_NON_NULL(TAG, acl, ERROR);
+
+                    while (cbor_value_is_valid(&aceMap))
+                    {
+                        char* name = NULL;
+                        size_t len = 0;
+                        CborType type = cbor_value_get_type(&aceMap);
+                        if (type == CborTextStringType)
+                        {
+                            cborFindResult = cbor_value_dup_text_string(&aceMap, &name, &len, NULL);
+                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACE Map.");
+                            cborFindResult = cbor_value_advance(&aceMap);
+                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACE Map.");
+                        }
+                        if (name)
+                        {
+                            // Subject -- Mandatory
+                            if (strcmp(name, OIC_JSON_SUBJECTID_NAME)  == 0)
+                            {
+                                char *subject = NULL;
+                                cborFindResult = cbor_value_dup_text_string(&aceMap, &subject, &len, NULL);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subject Value.");
+                                if(strcmp(subject, WILDCARD_RESOURCE_URI) == 0)
+                                {
+                                    ace->subjectuuid.id[0] = '*';
+                                }
+                                else
+                                {
+                                    OIC_LOG_V(DEBUG, TAG, "Converting subjectuuid = %s to uuid...", subject);
+                                    ret = ConvertStrToUuid(subject, &ace->subjectuuid);
+                                    VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
+                                }
+                                OICFree(subject);
+                            }
+
+                            // Resources -- Mandatory
+                            if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0)
+                            {
+                                CborValue resources = { .parser = NULL };
+                                cborFindResult = cbor_value_enter_container(&aceMap, &resources);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering a Resource Array.");
+
+                                while (cbor_value_is_valid(&resources))
+                                {
+                                    // rMap
+                                    CborValue rMap = { .parser = NULL  };
+                                    cborFindResult = cbor_value_enter_container(&resources, &rMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
+
+                                    OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
+                                    VERIFY_NON_NULL(TAG, rsrc, ERROR);
+                                    LL_APPEND(ace->resources, rsrc);
+
+                                    while(cbor_value_is_valid(&rMap))
+                                    {
+                                        char *rMapName = NULL;
+                                        size_t rMapNameLen = 0;
+                                        cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
+                                        cborFindResult = cbor_value_advance(&rMap);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
+
+                                        // "href"
+                                        if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
+                                        {
+                                            cborFindResult = cbor_value_dup_text_string(&rMap, &rsrc->href, &len, NULL);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
+                                        }
+
+                                        // "rt"
+                                        if (0 == strcmp(OIC_JSON_RT_NAME, rMapName) && cbor_value_is_array(&rMap))
+                                        {
+                                            cbor_value_get_array_length(&rMap, &rsrc->typeLen);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT array length.");
+                                            VERIFY_SUCCESS(TAG, (0 != rsrc->typeLen), ERROR);
+
+                                            rsrc->types = (char**)OICCalloc(rsrc->typeLen, sizeof(char*));
+                                            VERIFY_NON_NULL(TAG, rsrc->types, ERROR);
+
+                                            CborValue resourceTypes;
+                                            cborFindResult = cbor_value_enter_container(&rMap, &resourceTypes);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering RT Array.");
+
+                                            for(size_t i = 0; cbor_value_is_valid(&resourceTypes) && cbor_value_is_text_string(&resourceTypes); i++)
+                                            {
+                                                size_t readLen = 0;
+                                                cborFindResult = cbor_value_dup_text_string(&resourceTypes, &(rsrc->types[i]), &readLen, NULL);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding resource type.");
+                                                cborFindResult = cbor_value_advance(&resourceTypes);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing resource type.");
+                                            }
+                                        }
+
+                                        // "if"
+                                        if (0 == strcmp(OIC_JSON_IF_NAME, rMapName) && cbor_value_is_array(&rMap))
+                                        {
+                                            cbor_value_get_array_length(&rMap, &rsrc->interfaceLen);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF array length.");
+                                            VERIFY_SUCCESS(TAG, (0 != rsrc->interfaceLen), ERROR);
+
+                                            rsrc->interfaces = (char**)OICCalloc(rsrc->interfaceLen, sizeof(char*));
+                                            VERIFY_NON_NULL(TAG, rsrc->interfaces, ERROR);
+
+                                            CborValue interfaces;
+                                            cborFindResult = cbor_value_enter_container(&rMap, &interfaces);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering IF Array.");
+
+                                            for(size_t i = 0; cbor_value_is_valid(&interfaces) && cbor_value_is_text_string(&interfaces); i++)
+                                            {
+                                                size_t readLen = 0;
+                                                cborFindResult = cbor_value_dup_text_string(&interfaces, &(rsrc->interfaces[i]), &readLen, NULL);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF type.");
+                                                cborFindResult = cbor_value_advance(&interfaces);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing IF type.");
+                                            }
+                                        }
+
+                                        // "rel"
+                                        if (0 == strcmp(OIC_JSON_REL_NAME, rMapName))
+                                        {
+                                            cborFindResult = cbor_value_dup_text_string(&rMap, &rsrc->rel, &len, NULL);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding REL Value.");
+                                        }
+
+                                        if (cbor_value_is_valid(&rMap))
+                                        {
+                                            cborFindResult = cbor_value_advance(&rMap);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
+                                        }
+                                        OICFree(rMapName);
+                                    }
+
+                                    if (cbor_value_is_valid(&resources))
+                                    {
+                                        cborFindResult = cbor_value_advance(&resources);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Resource Array.");
+                                    }
+                                }
+                            }
+
+                            // Permissions -- Mandatory
+                            if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0)
+                            {
+                                uint64_t tmp64;
+                                cborFindResult = cbor_value_get_uint64(&aceMap, &tmp64);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a PERM Value.");
+                                ace->permission = (uint16_t)tmp64;
+                            }
+
+                            // TODO: Need to verfication for validity
+                            // Validity -- Not mandatory
+                            if(strcmp(name, OIC_JSON_VALIDITY_NAME) == 0)
+                            {
+                                CborValue validitiesMap = {.parser = NULL};
+                                size_t validitySize = 0;
+
+                                cborFindResult = cbor_value_get_array_length(&aceMap, &validitySize);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Validity Array Length.");
+
+                                cborFindResult = cbor_value_enter_container(&aceMap, &validitiesMap);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a validity Array Map.");
+
+                                while(cbor_value_is_valid(&validitiesMap))
+                                {
+                                    OicSecValidity_t* validity = (OicSecValidity_t*)OICCalloc(1, sizeof(OicSecValidity_t));
+                                    VERIFY_NON_NULL(TAG, validity, ERROR);
+                                    LL_APPEND(ace->validities, validity);
+
+                                    CborValue validityMap  = {.parser = NULL};
+                                    //period (string)
+                                    cborFindResult = cbor_value_enter_container(&validitiesMap, &validityMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a validity Map.");
+
+                                    size_t len = 0;
+                                    cborFindResult =cbor_value_dup_text_string(&validityMap, &validity->period, &len, NULL);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period value.");
+
+                                    //recurrence (string array)
+                                    CborValue recurrenceMap  = {.parser = NULL};
+                                    cborFindResult = cbor_value_enter_container(&validityMap, &recurrenceMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a recurrence array.");
+
+                                    cborFindResult = cbor_value_get_array_length(&recurrenceMap, &validity->recurrenceLen);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array.");
+
+                                    validity->recurrences = (char**)OICCalloc(validity->recurrenceLen, sizeof(char*));
+                                    VERIFY_NON_NULL(TAG, validity->recurrences, ERROR);
+
+                                    for(size_t i = 0; cbor_value_is_text_string(&recurrenceMap) && i < validity->recurrenceLen; i++)
+                                    {
+                                        cborFindResult = cbor_value_dup_text_string(&recurrenceMap, &validity->recurrences[i], &len, NULL);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a recurrence Value.");
+
+                                        cborFindResult = cbor_value_advance(&recurrenceMap);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a recurrences Array.");
+                                    }
+
+                                    cborFindResult = cbor_value_advance(&validitiesMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a validities Array.");
+                                }
+                            }
+                            OICFree(name);
+                        }
+
+                        if (type != CborMapType && cbor_value_is_valid(&aceMap))
+                        {
+                            cborFindResult = cbor_value_advance(&aceMap);
+                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Array.");
+                        }
+                    }
+
+                    if (cbor_value_is_valid(&acesArray))
+                    {
+                        cborFindResult = cbor_value_advance(&acesArray);
+                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Array.");
+                    }
+                }
+            }
+
+            //rownerID -- Mandatory
+            if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0)
+            {
+                char *stRowner = NULL;
+                cborFindResult = cbor_value_dup_text_string(&aclMap, &stRowner, &len, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
+                OIC_LOG_V(DEBUG, TAG, "Converting rownerid = %s to uuid...", stRowner);
+                ret = ConvertStrToUuid(stRowner, &acl->rownerID);
+                VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
+                OICFree(stRowner);
+            }
+            OICFree(tagName);
+        }
+        if (cbor_value_is_valid(&aclMap))
+        {
+            cborFindResult = cbor_value_advance(&aclMap);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Map.");
+        }
+    }
+
+exit:
+    if (cborFindResult != CborNoError)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to CBORPayloadToAcl");
+        DeleteACLList(acl);
+        acl = NULL;
+    }
+
+    return acl;
+}
+
+// This function converts CBOR format to ACL data.
+// Caller needs to invoke 'free' when done using
 // note: This function is used in unit test hence not declared static,
 OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
 {
@@ -1431,7 +1738,6 @@ static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest *
     if (payload)
     {
         OicSecAcl_t *newAcl = NULL;
-        OicSecAcl_t newAceList;
         OIC_LOG(DEBUG, TAG, "ACL payload from POST request << ");
         OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
 
@@ -1443,7 +1749,6 @@ static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest *
             OicSecAce_t* newAce = NULL;
             OicSecAce_t* tempAce1 = NULL;
             OicSecAce_t* tempAce2 = NULL;
-            newAceList.aces = NULL;
 
             LL_FOREACH_SAFE(newAcl->aces, newAce, tempAce1)
             {
@@ -1882,37 +2187,42 @@ const OicSecAce_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAce_t **
     return NULL;
 }
 
-OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size)
+OCStackResult InstallNewACL2(const OicSecAcl_t* acl)
 {
     OCStackResult ret = OC_STACK_ERROR;
 
-    // Convert CBOR format to ACL data. This will also validate the ACL data received.
-    OicSecAcl_t* newAcl = CBORPayloadToAcl(cborPayload, size);
+    if (!acl)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-    if (newAcl)
+    // Append the new ACL to existing ACL
+    OicSecAce_t* newAce = NULL;
+    LL_FOREACH(acl->aces, newAce)
     {
-        // Append the new ACL to existing ACL
-        OicSecAce_t* newAce = NULL;
-        LL_FOREACH(newAcl->aces, newAce)
-        {
-            LL_APPEND(gAcl->aces, newAce);
-        }
+        LL_APPEND(gAcl->aces, newAce);
+    }
 
-        size_t size = 0;
-        uint8_t *payload = NULL;
-        if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
-        {
-            if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
-            {
-                ret = OC_STACK_OK;
-            }
-            OICFree(payload);
-        }
+    size_t size = 0;
+    uint8_t *payload = NULL;
+    ret = AclToCBORPayload(gAcl, &payload, &size);
+    if (OC_STACK_OK == ret)
+    {
+        ret = UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size);
+        OICFree(payload);
     }
 
     return ret;
 }
 
+OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size)
+{
+    // Convert CBOR format to ACL data. This will also validate the ACL data received.
+    OicSecAcl_t* newAcl = CBORPayloadToAcl(cborPayload, size);
+
+    return InstallNewACL2(newAcl);
+}
+
 /**
  * This function generates default ACE for security resource in case of owned status.
  *
index 24371b8..4dc8699 100644 (file)
@@ -29,6 +29,7 @@
 #include <strings.h>
 #endif
 #include <stdint.h>
+#include <stdbool.h>
 
 #include "cainterface.h"
 #include "payload_logging.h"
 #include "psinterface.h"
 #include "pinoxmcommon.h"
 
+#ifdef __unix__
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
 #ifdef __WITH_DTLS__
 #include "global.h"
 #endif
 
 #define TAG  "SRM-CREDL"
 
+/** Max credential types number used for TLS */
+#define MAX_TYPE 2
 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
  * The value of payload size is increased until reaching belox max cbor size. */
 static const uint16_t CBOR_SIZE = 2048;
@@ -119,6 +129,34 @@ void DeleteCredList(OicSecCred_t* cred)
     }
 }
 
+size_t GetCredKeyDataSize(const OicSecCred_t* cred)
+{
+    size_t size = 0;
+    if (cred)
+    {
+        OicSecCred_t *credPtr = NULL, *credTmp = NULL;
+        LL_FOREACH_SAFE((OicSecCred_t*)cred, credPtr, credTmp)
+        {
+            if (credPtr->privateData.data && 0 < credPtr->privateData.len)
+            {
+                size += credPtr->privateData.len;
+            }
+#if defined(__WITH_X509__) || defined(__WITH_TLS__)
+            if (credPtr->publicData.data && 0 < credPtr->publicData.len)
+            {
+                size += credPtr->publicData.len;
+            }
+            if (credPtr->optionalData.data && 0 < credPtr->optionalData.len)
+            {
+                size += credPtr->optionalData.len;
+            }
+#endif
+        }
+    }
+    OIC_LOG_V(DEBUG, TAG, "Cred Key Data Size : %d\n", size);
+    return size;
+}
+
 static size_t OicSecCredCount(const OicSecCred_t *secCred)
 {
     size_t size = 0;
@@ -262,8 +300,8 @@ OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload
             cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_JSON_ENCODING_NAME,
                 strlen(OIC_JSON_ENCODING_NAME));
             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Tag.");
-            cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_SEC_ENCODING_RAW,
-                strlen(OIC_SEC_ENCODING_RAW));
+            cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_SEC_ENCODING_DER,
+                strlen(OIC_SEC_ENCODING_DER));
             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Value.");
 
             cborEncoderResult = cbor_encoder_close_container(&credMap, &publicMap);
@@ -414,6 +452,22 @@ OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload
                     cred->privateData.len);
                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
             }
+            else if(OIC_ENCODING_DER == cred->privateData.encoding)
+            {
+                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
+                    strlen(OIC_JSON_ENCODING_NAME));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
+                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_DER,
+                    strlen(OIC_SEC_ENCODING_DER));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");
+
+                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
+                    strlen(OIC_JSON_DATA_NAME));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
+                cborEncoderResult = cbor_encode_byte_string(&privateMap, cred->privateData.data,
+                    cred->privateData.len);
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
+            }
             else
             {
                 OIC_LOG(ERROR, TAG, "Unknow encoding type for private data.");
@@ -994,7 +1048,9 @@ static bool UpdatePersistentStorage(const OicSecCred_t *cred)
     if (cred)
     {
         uint8_t *payload = NULL;
-        size_t size = 0;
+        // This added '256' is arbitrary value that is added to cover the name of the resource, map addition and ending
+        size_t size = GetCredKeyDataSize(cred);
+        size += (256 * OicSecCredCount(cred));
         int secureFlag = 0;
         OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
         if ((OC_STACK_OK == res) && payload)
@@ -1420,6 +1476,11 @@ static OCEntityHandlerResult HandleGetRequest (const OCEntityHandlerRequest * eh
     int secureFlag = 1;
 
     const OicSecCred_t *cred = gCred;
+
+    size_t credCnt = 0;
+    // This added '256' is arbitrary value that is added to cover the name of the resource, map addition and ending
+    size = GetCredKeyDataSize(cred);
+    size += (256 * OicSecCredCount(cred));
     OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
 
     // A device should always have a default cred. Therefore, payload should never be NULL.
@@ -1865,6 +1926,10 @@ OCStackResult SetCredRownerId(const OicUuid_t* newROwner)
         memcpy(prevId.id, gCred->rownerID.id, sizeof(prevId.id));
         memcpy(gCred->rownerID.id, newROwner->id, sizeof(newROwner->id));
 
+        size_t credCnt = 0;
+        // This added '256' is arbitrary value that is added to cover the name of the resource, map addition and ending
+        size = GetCredKeyDataSize(gCred);
+        size += (256 * OicSecCredCount(gCred));
         ret = CredToCBORPayload(gCred, &cborPayload, &size, secureFlag);
         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
 
@@ -1896,14 +1961,19 @@ OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
 #ifdef __WITH_TLS__
 void GetDerCaCert(ByteArray * crt)
 {
+    if (NULL == crt)
+    {
+        return;
+    }
     uint8_t *data = NULL;
+    crt->len = 0;
     OCStackResult ret = OC_STACK_ERROR;
     OicSecCred_t * cred;
     OicSecCred_t * temp = NULL;
-    OIC_LOG(DEBUG, TAG, "IN GetDerCaCert");
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
     LL_FOREACH(gCred, temp)
     {
-        if (0==memcmp((temp->credUsage), TRUST_CA, sizeof(TRUST_CA)))
+        if (SIGNED_ASYMMETRIC_KEY == temp->credType && 0 == memcmp((temp->credUsage), TRUST_CA, sizeof(TRUST_CA)))
         {
             OIC_LOG_V(DEBUG, TAG, "len: %d, crt len: %d", temp->optionalData.len, crt->len);
             if(OIC_ENCODING_BASE64 == temp->optionalData.encoding)
@@ -1931,33 +2001,115 @@ void GetDerCaCert(ByteArray * crt)
             OIC_LOG_V(DEBUG, TAG, "Trust CA Found!! %d", crt->len);
         }
     }
-    if(!crt->len) OIC_LOG(DEBUG, TAG, "Trust CA Not Found!!");
+    if(0 == crt->len)
+    {
+        OIC_LOG(DEBUG, TAG, "Trust CA Not Found!!");
+    }
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
     return;
 }
 
-
-void GetDerKey(ByteArray * key)
+void GetDerOwnCert(ByteArray * crt)
 {
-    // TODO Add implementation
-    key->data = NULL;
-    key->len = 0;
+    if (NULL == crt)
+    {
+        return;
+    }
+    crt->len = 0;
+    uint8_t *data = NULL;
+    OicSecCred_t * temp = NULL;
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    LL_FOREACH(gCred, temp)
+    {
+        if (SIGNED_ASYMMETRIC_KEY == temp->credType && 0 == memcmp((temp->credUsage), PRIMARY_CERT, sizeof(PRIMARY_CERT)))
+        {
+            OIC_LOG_V(DEBUG, TAG, "len: %d, crt len: %d", temp->publicData.len, crt->len);
+            crt->data = OICRealloc(crt->data, crt->len + temp->publicData.len);
+            memcpy(crt->data + crt->len, temp->publicData.data, temp->publicData.len);
+            crt->len += temp->publicData.len;
+
+            OIC_LOG_V(DEBUG, TAG, "Trust CA Found!! %d", crt->len);
+        }
+    }
+    if(0 == crt->len)
+    {
+        OIC_LOG(DEBUG, TAG, "Trust CA Not Found!!");
+    }
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
     return;
 }
 
-void GetDerOwnCert(ByteArray * cert)
+void GetDerKey(ByteArray * key)
 {
-    // TODO Add implementation
-    cert->data = NULL;
-    cert->len = 0;
-    return;
+    if (NULL == key)
+    {
+        return;
+    }
+
+    uint8_t *data = NULL;
+    OicSecCred_t * temp = NULL;
+    key->len = 0;
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    LL_FOREACH(gCred, temp)
+    {
+        if (SIGNED_ASYMMETRIC_KEY == temp->credType && 0 == memcmp((temp->credUsage), PRIMARY_CERT, sizeof(PRIMARY_CERT)))
+        {
+            OIC_LOG_V(DEBUG, TAG, "len: %d, key len: %d", temp->privateData.len, key->len);
+            key->data = OICRealloc(key->data, key->len + temp->privateData.len);
+            memcpy(key->data + key->len, temp->privateData.data, temp->privateData.len);
+            key->len += temp->privateData.len;
+
+            OIC_LOG_V(DEBUG, TAG, "Key Found!! %d", key->len);
+        }
+    }
+    if(0 == key->len) 
+    {
+        OIC_LOG(DEBUG, TAG, "Key Not Found!!");
+    }
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 }
-void GetPkixInfo(PkiInfo_t * inf)
+
+void InitCipherSuiteList(bool * list)
 {
     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
-    GetDerOwnCert(&inf->crt);
-    GetDerKey(&inf->key);
-    GetDerCaCert(&inf->ca);
+    if (NULL == list)
+    {
+        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+        OIC_LOG(DEBUG, TAG, "NULL list param");
+        return;
+    }
+    OicSecCred_t * temp = NULL;
+    LL_FOREACH(gCred, temp)
+    {
+        switch (temp->credType)
+        {
+            case SYMMETRIC_PAIR_WISE_KEY:
+            {
+                list[0] = true;
+                OIC_LOG(DEBUG, TAG, "SYMMETRIC_PAIR_WISE_KEY found");
+                break;
+            }
+            case SIGNED_ASYMMETRIC_KEY:
+            {
+                list[1] = true;
+                OIC_LOG(DEBUG, TAG, "SIGNED_ASYMMETRIC_KEY found");
+                break;
+            }
+            case SYMMETRIC_GROUP_KEY:
+            case ASYMMETRIC_KEY:
+            case PIN_PASSWORD:
+            case ASYMMETRIC_ENCRYPTION_KEY:
+            {
+                OIC_LOG(WARNING, TAG, "Unsupported credential type for TLS.");
+                break;
+            }
+            default:
+            {
+                OIC_LOG(WARNING, TAG, "Unknow credential type for TLS.");
+                break;
+            }
+        }
+    }
     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 }
-
 #endif
index a8b4fd8..6b1aaff 100644 (file)
 #include "doxmresource.h"
 #include "ocpayload.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 #include "crlresource.h"
 #include "crl.h"
+#include "ocpayloadcbor.h"
+#include "base64.h"
+#include <time.h>
 
 #define TAG  "SRM-CRL"
 
@@ -42,7 +46,9 @@
 #define OIC_CBOR_CRL_DATA           "CRLData"
 #define CRL_DEFAULT_CRL_ID          (1)
 #define CRL_DEFAULT_THIS_UPDATE     "150101000000Z"
+#define CRL_DEFAULT_LAST_UPDATE     "20150701000000"
 #define CRL_DEFAULT_CRL_DATA        "-"
+#define CRL_MAP_SIZE                (3)
 
 static OCResourceHandle     gCrlHandle  = NULL;
 static OicSecCrl_t         *gCrl        = NULL;
@@ -54,10 +60,7 @@ static const uint16_t CBOR_SIZE = 1024;
 // Max cbor size payload.
 static const uint16_t CBOR_MAX_SIZE = 4400;
 
-// PSTAT Map size - Number of mandatory items
-static const uint8_t CRL_MAP_SIZE = 3;
-
-void DeleteCrlBinData(OicSecCrl_t *crl)
+void DeleteCrl(OicSecCrl_t *crl)
 {
     if (crl)
     {
@@ -72,7 +75,213 @@ void DeleteCrlBinData(OicSecCrl_t *crl)
     }
 }
 
-OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size)
+static void printCrl(const OicSecCrl_t *crl)
+{
+    OIC_LOG(DEBUG, TAG, "Crl object contain:");
+    OIC_LOG_V(DEBUG, TAG, "id = %d", crl->CrlId);
+    OIC_LOG_V(DEBUG, TAG, "this update = %s", crl->ThisUpdate.data);
+
+    OIC_LOG(DEBUG, TAG, "crl:");
+    OIC_LOG_V(DEBUG, TAG, "encoding = %d", crl->CrlData.encoding);
+    OIC_LOG_V(DEBUG, TAG, "data (length = %zu):", crl->CrlData.len);
+    OIC_LOG_BUFFER(DEBUG, TAG, crl->CrlData.data, crl->CrlData.len);
+}
+
+static bool copyByteArray(const uint8_t *in, size_t in_len, uint8_t **out, size_t *out_len)
+{
+    OICFree(*out);
+    uint8_t *tmp = OICMalloc(in_len);
+    if (!tmp)
+    {
+        return false;
+    }
+    memcpy(tmp, in, in_len);
+    *out = tmp;
+    *out_len = in_len;
+    return true;
+}
+
+static bool copyCrl(const OicSecCrl_t *in, OicSecCrl_t *out)
+{
+    bool result = false;
+
+    if (!in || !out)
+    {
+        OIC_LOG(ERROR, TAG, "in or out crl is NULL");
+        return false;
+    }
+
+    out->CrlId = in->CrlId;
+
+    result = copyByteArray(in->ThisUpdate.data, in->ThisUpdate.len, &out->ThisUpdate.data, &out->ThisUpdate.len);
+    if (!result)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate memory for ThisUpdate");
+        return false;
+    }
+
+    result = copyByteArray(in->CrlData.data, in->CrlData.len, &out->CrlData.data, &out->CrlData.len);
+    if (!result)
+    {
+        OIC_LOG(ERROR, TAG, "Can't allocate memory for CrlData");
+        return false;
+    }
+
+    return result;
+}
+
+static CborError setPubDataType(CborEncoder *out, const char *name, const OicSecKey_t *value)
+{
+    if (!out || !name || !value)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__);
+        return CborErrorInternalError;
+    }
+
+    CborEncoder map;
+
+    const char *encoding = NULL;
+    bool binary_field = false;
+
+    size_t mapSize = 0;
+
+    mapSize++;
+    switch(value->encoding)
+    {
+        case OIC_ENCODING_RAW:
+            binary_field = true;
+            encoding = OIC_SEC_ENCODING_RAW;
+            break;
+        case OIC_ENCODING_BASE64:
+            encoding = OIC_SEC_ENCODING_BASE64;
+            break;
+        case OIC_ENCODING_DER:
+            binary_field = true;
+            encoding = OIC_SEC_ENCODING_DER;
+            break;
+        case OIC_ENCODING_PEM:
+            encoding = OIC_SEC_ENCODING_PEM;
+            break;
+        default:
+            OIC_LOG(ERROR, TAG, "Received UNKNOWN encoding, exit!");
+            return CborErrorInternalError;
+    }
+
+    if (value->data)
+    {
+        mapSize++;
+    }
+
+    CborError result = CborNoError;
+    result = cbor_encode_text_string(out, name, strlen(name));
+    VERIFY_CBOR_SUCCESS(TAG, result, "Failed Adding name Tag.");
+
+    result = cbor_encoder_create_map(out, &map, mapSize);
+    VERIFY_CBOR_SUCCESS(TAG, result, "Failed creating name map");
+
+    if (encoding)
+    {
+        result = cbor_encode_text_string(&map, OIC_JSON_ENCODING_NAME,
+                                         strlen(OIC_JSON_ENCODING_NAME));
+        VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add encoding tag.")
+        result = cbor_encode_text_string(&map, encoding, strlen(encoding));
+        VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add encoding value.");
+    };
+
+    if (value->data)
+    {
+        result = cbor_encode_text_string(&map, OIC_JSON_DATA_NAME, strlen(OIC_JSON_DATA_NAME));
+        VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add data tag.");
+        if (binary_field)
+        {
+            result = cbor_encode_byte_string(&map, value->data, value->len);
+        }
+        else
+        {
+            result = cbor_encode_text_string(&map, (const char *)value->data, value->len);
+        }
+        VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add data value.");
+    }
+
+    result = cbor_encoder_close_container(out, &map);
+    VERIFY_CBOR_SUCCESS(TAG, result, "Failed Closing PrivateData Map.");
+
+exit:
+    return result;
+}
+
+static CborError getPubDataType(CborValue *in, const char *name, OicSecKey_t *value)
+{
+    if (!in || !name || !value)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__);
+        return CborErrorInternalError;
+    }
+
+    CborError result = CborNoError;
+    char *encoding = NULL;
+
+    CborValue crlNode = { .parser = NULL };
+    result = cbor_value_map_find_value(in, name, &crlNode);
+    if (CborNoError == result && cbor_value_is_map(&crlNode))
+    {
+        CborValue crlMap = { .parser = NULL };
+        result = cbor_value_enter_container(&crlNode, &crlMap);
+
+        while(cbor_value_is_valid(&crlMap) && cbor_value_is_text_string(&crlMap))
+        {
+            char *property = NULL;
+            size_t length = 0;
+            result = cbor_value_dup_text_string(&crlMap, &property, &length, NULL);
+            VERIFY_CBOR_SUCCESS(TAG, result, "Failed Get first crl ojbject tag.");
+            result = cbor_value_advance(&crlMap);
+            VERIFY_CBOR_SUCCESS(TAG, result, "Failed to advance crlMap");
+
+            if (0 == strcmp(OIC_JSON_DATA_NAME, property))
+            {
+                if (cbor_value_is_byte_string(&crlMap))
+                {
+                    result = cbor_value_dup_byte_string(&crlMap, &value->data, &value->len, NULL);
+                }
+                else if(cbor_value_is_text_string(&crlMap))
+                {
+                    char *buffer = NULL;
+                    result = cbor_value_dup_text_string(&crlMap, &buffer, &value->len, NULL);
+                    value->data = (uint8_t *)buffer;
+                }
+                else
+                {
+                    result = CborErrorUnknownType;
+                    OIC_LOG(ERROR, TAG, "Unknown type for crl->data.");
+                }
+                VERIFY_CBOR_SUCCESS(TAG, result, "Failed to read crl->data");
+            }
+            else if (0 == strcmp(OIC_JSON_ENCODING_NAME, property))
+            {
+                size_t encoding_len = 0;
+                result = cbor_value_dup_text_string(&crlMap, &encoding, &encoding_len, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, result, "Failed to read crl->encdoing");
+            }
+            OICFree(property);
+        }
+    }
+    VERIFY_CBOR_SUCCESS(TAG, result, "Failed to find root node");
+
+    if (encoding)
+    {
+        OicEncodingType_t type = OIC_ENCODING_UNKNOW;
+        if (0 == strcmp(encoding, OIC_SEC_ENCODING_BASE64)) type = OIC_ENCODING_BASE64;
+        else if (0 == strcmp(encoding, OIC_SEC_ENCODING_DER)) type = OIC_ENCODING_DER;
+        else if (0 == strcmp(encoding, OIC_SEC_ENCODING_PEM)) type = OIC_ENCODING_PEM;
+        else if (0 == strcmp(encoding, OIC_SEC_ENCODING_RAW)) type = OIC_ENCODING_RAW;
+
+        value->encoding = type;
+    }
+exit:
+    return result;
+}
+
+OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size, char *lastUpdate)
 {
     if (NULL == crl || NULL == payload || NULL != *payload || NULL == size)
     {
@@ -88,6 +297,14 @@ OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t
     *payload = NULL;
     *size = 0;
 
+    size_t mapSize = CRL_MAP_SIZE;
+    if (lastUpdate)
+    {
+        mapSize++;
+    }
+
+    printCrl(crl);
+
     OCStackResult ret = OC_STACK_ERROR;
 
     CborEncoder encoder;
@@ -99,31 +316,37 @@ OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t
     VERIFY_NON_NULL(TAG, outPayload, ERROR);
     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
 
-    cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, CRL_MAP_SIZE);
+    cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, mapSize);
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create CRL Map");
 
     //CRLId -- Mandatory
-    cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_ID,
-        strlen(OIC_CBOR_CRL_ID));
+    cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_CRL_ID,
+        strlen(OC_RSRVD_CRL_ID));
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL ID");
     cborEncoderResult = cbor_encode_int(&crlMap, crl->CrlId);
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL Id value");
 
     //ThisUpdate -- Mandatory
-    cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_THIS_UPDATE,
-        strlen(OIC_CBOR_CRL_THIS_UPDATE));
+    cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_THIS_UPDATE,
+        strlen(OC_RSRVD_THIS_UPDATE));
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl update");
-    cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->ThisUpdate.data,
+    cborEncoderResult = cbor_encode_text_string(&crlMap, (const char *)crl->ThisUpdate.data,
                                                 crl->ThisUpdate.len);
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl Update value");
 
     //CRLData -- Mandatory
-    cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_DATA,
-        strlen(OIC_CBOR_CRL_DATA));
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl data name");
-    cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->CrlData.data,
-                                                crl->CrlData.len);
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl data value");
+    cborEncoderResult = setPubDataType(&crlMap, OC_RSRVD_CRL, &crl->CrlData);
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRLData object");
+
+    //lastUpdate - internal field
+    if (lastUpdate)
+    {
+        cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_LAST_UPDATE,
+            strlen(OC_RSRVD_LAST_UPDATE));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update tag");
+        cborEncoderResult = cbor_encode_text_string(&crlMap, lastUpdate, strlen(lastUpdate));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update value");
+    }
 
     cborEncoderResult = cbor_encoder_close_container(&encoder, &crlMap);
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add close Crl map");
@@ -140,7 +363,7 @@ exit:
         // Since the allocated initial memory failed, double the memory.
         cborLen += encoder.ptr - encoder.end;
         cborEncoderResult = CborNoError;
-        ret = CrlToCBORPayload(crl, payload, &cborLen);
+        ret = CrlToCBORPayload(crl, payload, &cborLen, lastUpdate);
     }
 
     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
@@ -164,7 +387,7 @@ OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
     }
 
     OCStackResult ret = OC_STACK_ERROR;
-    *secCrl = NULL;
+    OicSecCrl_t *crl = NULL;
 
     CborValue crlCbor = {.parser = NULL};
     CborParser parser = {.end = NULL};
@@ -172,15 +395,13 @@ OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
 
     cbor_parser_init(cborPayload, size, 0, &parser, &crlCbor);
     CborValue crlMap = { .parser = NULL};
-    OicSecCrl_t *crl = NULL;
-    size_t outLen = 0;
     cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap);
     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter Crl map");
 
     crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
     VERIFY_NON_NULL(TAG, crl, ERROR);
 
-    cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_ID, &crlMap);
+    cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_CRL_ID, &crlMap);
     if (CborNoError == cborFindResult && cbor_value_is_integer(&crlMap))
     {
         int CrlId;
@@ -190,84 +411,75 @@ OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
         crl->CrlId = (uint16_t)CrlId;
     }
 
-    cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_THIS_UPDATE, &crlMap);
-    if (CborNoError == cborFindResult && cbor_value_is_byte_string(&crlMap))
-    {
-        cborFindResult = cbor_value_dup_byte_string(&crlMap,
-            &crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL);
-        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
-    }
-    cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_DATA, &crlMap);
-    if (CborNoError == cborFindResult && cbor_value_is_byte_string(&crlMap))
+    cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_THIS_UPDATE, &crlMap);
+    if (CborNoError == cborFindResult && cbor_value_is_text_string(&crlMap))
     {
-        cborFindResult = cbor_value_dup_byte_string(&crlMap,
-                         &crl->CrlData.data, &crl->CrlData.len, NULL);
+        cborFindResult = cbor_value_dup_text_string(&crlMap,
+                (char **)&crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL);
         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
     }
 
+    cborFindResult = getPubDataType(&crlCbor, OC_RSRVD_CRL, &crl->CrlData);
+    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read CRL.");
+
+    printCrl(crl);
+
     *secCrl = crl;
     ret = OC_STACK_OK;
 exit:
     if (CborNoError != cborFindResult)
     {
         // PUT/POST CBOR may not have mandatory values set default values.
-        if (gCrl)
-        {
-            OIC_LOG (DEBUG, TAG, "Set default values");
-            crl->CrlId = gCrl->CrlId;
-            if (crl->ThisUpdate.data)
-            {
-                OICFree(crl->ThisUpdate.data);
-            }
-            outLen = gCrl->ThisUpdate.len;
-            crl->ThisUpdate.data = (uint8_t*) OICMalloc(outLen);
-            if (crl->ThisUpdate.data)
-            {
-                memcpy(crl->ThisUpdate.data, gCrl->ThisUpdate.data, outLen);
-                crl->ThisUpdate.len = outLen;
-            }
-            else
-            {
-                crl->ThisUpdate.len = 0;
-                OIC_LOG(ERROR, TAG, "Set default failed");
-            }
-            if (crl->CrlData.data)
-            {
-                OICFree(crl->CrlData.data);
-            }
-            outLen = gCrl->CrlData.len;
-            crl->CrlData.data = (uint8_t*) OICMalloc(outLen);
-            if (crl->CrlData.data && gCrl->CrlData.data)
-            {
-                memcpy(crl->CrlData.data, gCrl->CrlData.data, outLen);
-                crl->CrlData.len = outLen;
-            }
-            else
-            {
-                crl->CrlData.len = 0;
-                OIC_LOG (ERROR, TAG, "Set default failed");
-            }
+        OIC_LOG (DEBUG, TAG, "Set default values");
 
+        if (copyCrl(gCrl, crl))
+        {
             *secCrl = crl;
             ret = OC_STACK_OK;
         }
         else
         {
-            OIC_LOG (ERROR, TAG, "CBORPayloadToCrl failed");
-            DeleteCrlBinData(crl);
+            DeleteCrl(crl);
             crl = NULL;
             ret = OC_STACK_ERROR;
+            OIC_LOG (ERROR, TAG, "Can't set default crl");
         }
     }
     return ret;
 }
 
-OCStackResult UpdateCRLResource(const OicSecCrl_t *crl)
+static void getCurrentUTCTime(char *out, size_t len)
 {
+    //TODO: how to implement it in cross-platform way?
+    time_t rawtime;
+    struct tm * timeinfo;
+
+    time ( &rawtime );
+    timeinfo = localtime ( &rawtime );
+
+    snprintf(out, len, "%04d%02d%02d%02d%02d%02d",
+            timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday,
+            timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
+}
+
+OCStackResult UpdateCRLResource(OicSecCrl_t *crl)
+{
+    static uint16_t crlid = 0;
     uint8_t *payload = NULL;
     size_t size = 0;
 
-    OCStackResult res = CrlToCBORPayload((OicSecCrl_t *) crl, &payload, &size);
+    crl->CrlId = crlid++;
+
+    if (!copyCrl(crl, gCrl))
+    {
+        OIC_LOG(ERROR, TAG, "Can't update global crl");
+        return OC_STACK_ERROR;
+    }
+
+    char currentTime[32] = {0};
+    getCurrentUTCTime(currentTime, sizeof(currentTime));
+
+    OCStackResult res = CrlToCBORPayload((const OicSecCrl_t *) crl, &payload, &size, currentTime);
     if (OC_STACK_OK != res)
     {
         return res;
@@ -285,31 +497,16 @@ static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *
 
     if (payload)
     {
-        OIC_LOG(INFO, TAG, "UpdateSVRDB...");
+        OIC_LOG(INFO, TAG, "Update SVR DB...");
         CBORPayloadToCrl(payload, size, &crl);
         VERIFY_NON_NULL(TAG, crl, ERROR);
 
-        gCrl->CrlId = crl->CrlId;
-
-        OICFree(gCrl->ThisUpdate.data);
-        gCrl->ThisUpdate.data = NULL;
-        gCrl->ThisUpdate.data = OICMalloc(crl->ThisUpdate.len);
-        VERIFY_NON_NULL(TAG, gCrl->ThisUpdate.data, ERROR);
-        memcpy(gCrl->ThisUpdate.data, crl->ThisUpdate.data, crl->ThisUpdate.len);
-        gCrl->ThisUpdate.len = crl->ThisUpdate.len;
-
-        OICFree(gCrl->CrlData.data);
-        gCrl->CrlData.data = OICMalloc(crl->CrlData.len);
-        VERIFY_NON_NULL(TAG, gCrl->CrlData.data, ERROR);
-        memcpy(gCrl->CrlData.data, crl->CrlData.data, crl->CrlData.len);
-        gCrl->CrlData.len = crl->CrlData.len;
-
-        if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size))
+        if (OC_STACK_OK == UpdateCRLResource(crl))
         {
             ehRet = OC_EH_RESOURCE_CREATED;
         }
 
-        DeleteCrlBinData(crl);
+        DeleteCrl(crl);
     }
 
 exit:
@@ -399,28 +596,23 @@ static OicSecCrl_t *GetCrlDefault()
     {
         return NULL;
     }
+
     defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
 
-    defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
-    defaultCrl->CrlData.data = (uint8_t*) OICMalloc(defaultCrl->CrlData.len);
-    if (defaultCrl->CrlData.data)
-    {
-        memcpy(defaultCrl->CrlData.data, CRL_DEFAULT_CRL_DATA, defaultCrl->CrlData.len);
-    }
-    else
-    {
-        defaultCrl->CrlData.len = 0;
-    }
+    bool result1 = copyByteArray((const uint8_t *)CRL_DEFAULT_CRL_DATA,
+                                 strlen(CRL_DEFAULT_CRL_DATA),
+                                 &defaultCrl->CrlData.data,
+                                 &defaultCrl->CrlData.len);
 
-    defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
-    defaultCrl->ThisUpdate.data = (uint8_t*) OICMalloc(defaultCrl->ThisUpdate.len);
-    if (defaultCrl->ThisUpdate.data)
-    {
-        memcpy(defaultCrl->ThisUpdate.data, CRL_DEFAULT_THIS_UPDATE, defaultCrl->ThisUpdate.len);
-    }
-    else
+    bool result2 = copyByteArray((const uint8_t *)CRL_DEFAULT_THIS_UPDATE,
+                                 strlen(CRL_DEFAULT_THIS_UPDATE),
+                                 &defaultCrl->ThisUpdate.data,
+                                 &defaultCrl->ThisUpdate.len);
+
+    if (!result1 || !result2)
     {
-        defaultCrl->ThisUpdate.len = 0;
+        DeleteCrl(defaultCrl);
+        return NULL;
     }
 
     return defaultCrl;
@@ -473,7 +665,7 @@ OCStackResult DeInitCRLResource()
 {
     OCStackResult result = OCDeleteResource(gCrlHandle);
     gCrlHandle = NULL;
-    DeleteCrlBinData(gCrl);
+    DeleteCrl(gCrl);
     gCrl = NULL;
     return result;
 }
@@ -505,6 +697,53 @@ OicSecCrl_t *GetCRLResource()
     return crl;
 }
 
+OCStackResult getLastUpdateFromDB(char **lastUpdate)
+{
+    OCStackResult result = OC_STACK_OK;
+
+    OCPayload *payload = NULL;
+    uint8_t *data = NULL;
+    size_t size = 0;
+
+    if (!lastUpdate)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    result = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "Can't get crl data from database");
+        goto exit;
+    }
+
+    result = OCParsePayload(&payload, PAYLOAD_TYPE_REPRESENTATION, data, size);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "Can't parse cbor data from DB");
+        goto exit;
+    }
+
+    if (!OCRepPayloadGetPropString((const OCRepPayload*)payload, OC_RSRVD_LAST_UPDATE, lastUpdate))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_LAST_UPDATE);
+        result = OC_STACK_ERROR;
+    }
+
+exit:
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG(DEBUG, TAG, "Assume you are first time get Crl, and it can be absent in database");
+        OIC_LOG_V(DEBUG, TAG, "Return default last update time %s", CRL_DEFAULT_LAST_UPDATE);
+
+        *lastUpdate = OICStrdup(CRL_DEFAULT_LAST_UPDATE);
+        result = OC_STACK_OK;
+    }
+    OCPayloadDestroy((OCPayload *)payload);
+
+    return result;
+}
+
 uint8_t *GetCrl()
 {
     uint8_t *data = NULL;
@@ -518,22 +757,63 @@ uint8_t *GetCrl()
     return NULL;
 }
 
-void  GetDerCrl(ByteArray* crlArray)
+void GetDerCrl(ByteArray* out)
 {
-    if(NULL == crlArray)
+    if(NULL == out)
+    {
+        return;
+    }
+
+    OicSecCrl_t *crlRes = GetCRLResource();
+
+    if(NULL == crlRes)
     {
         return;
     }
-    OicSecCrl_t * crlRes = GetCRLResource();
-    if (NULL != crlArray->data && NULL != crlRes
-        && NULL !=crlRes->CrlData.data && crlRes->CrlData.len <= crlArray->len)
+
+    OicSecKey_t *crl = &crlRes->CrlData;
+
+    if (OIC_ENCODING_BASE64 == crl->encoding)
+    {
+        size_t outSize = B64DECODE_OUT_SAFESIZE((crl->len + 1));
+        uint8_t *out = OICCalloc(1, outSize);
+        if (!out)
+        {
+            OIC_LOG(ERROR, TAG, "Can't allocate memory for base64 str");
+            return;
+        }
+        uint32_t len = 0;
+
+        if(B64_OK == b64Decode((char*)crl->data, crl->len, out, outSize, &len))
+        {
+            memcpy(crl->data, out, len);
+            crl->len = (size_t)len;
+
+            OIC_LOG (ERROR, TAG, "Crl successfully decoded to base64.");
+        }
+        else
+        {
+            OIC_LOG (ERROR, TAG, "Base64 decoding failed.");
+        }
+    }
+
+    out->len = 0;
+
+#ifdef __WITH_X509__
+    char *str = "Not enough space in out buffer to store crl!";
+    if (out->data && crl->data && crl->len <= out->len)
+#else
+    char *str = "Can't allocate memory for out->data";
+    out->data = OICMalloc(crl->len);
+    if (out->data)
+#endif
     {
-        memcpy(crlArray->data, crlRes->CrlData.data, crlRes->CrlData.len);
-        crlArray->len = crlRes->CrlData.len;
+        memcpy(out->data, crl->data, crl->len);
+        out->len = crl->len;
     }
     else
     {
-        crlArray->len = 0;
+        OIC_LOG_V(ERROR, TAG, "%s", str);
     }
-    DeleteCrlBinData(crlRes);
+    DeleteCrl(crlRes);
 }
diff --git a/resource/csdk/security/src/pkix_interface.c b/resource/csdk/security/src/pkix_interface.c
new file mode 100644 (file)
index 0000000..8949aa6
--- /dev/null
@@ -0,0 +1,36 @@
+//******************************************************************
+//
+// Copyright 2016 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "pkix_interface.h"
+#include "credresource.h"
+#include "crlresource.h"
+#include "logger.h"
+
+#define TAG "SRM-PKIX-INTERFACE"
+
+void GetPkixInfo(PkiInfo_t * inf)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    GetDerOwnCert(&inf->crt);
+    GetDerKey(&inf->key);
+    GetDerCaCert(&inf->ca);
+    GetDerCrl(&inf->crl);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
index d660058..bb5fab1 100644 (file)
@@ -183,6 +183,7 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
     uint8_t *credCbor = NULL;
     uint8_t *pconfCbor = NULL;
     uint8_t *resetPfCbor = NULL;
+    uint8_t *crlCbor = NULL;
 
     int64_t cborEncoderResult = CborNoError;
     OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
@@ -196,6 +197,7 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
         size_t credCborLen = 0;
         size_t pconfCborLen = 0;
         size_t resetPfCborLen = 0;
+        size_t crlCborLen = 0;
 
         // Gets each secure virtual resource from persistent storage
         // this local scoping intended, for destroying large cbor instances after use
@@ -254,13 +256,26 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
                 cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
             }
+            int64_t cborFindCrlResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRL_NAME, &curVal);
+            if (CborNoError == cborFindCrlResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindCrlResult = cbor_value_dup_byte_string(&curVal, &crlCbor, &crlCborLen, NULL);
+                if (CborNoError != cborFindCrlResult && CborErrorOutOfMemory != cborFindCrlResult)
+                {
+                    OIC_LOG(ERROR, TAG, "Failed Finding optional CRL Name Value.");
+                }
+                else
+                {
+                    OIC_LOG(INFO, TAG, "Successfully Finding optional CRL Name Value.");
+                }
+            }
         }
 
         // Updates the added |psPayload| with the existing secure virtual resource(s)
         // this local scoping intended, for destroying large cbor instances after use
         {
             size_t size = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
-                        + svcCborLen + credCborLen + pconfCborLen + resetPfCborLen
+                        + svcCborLen + credCborLen + pconfCborLen + resetPfCborLen + crlCborLen
                         + psSize + 255;
             // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
 
@@ -335,6 +350,13 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
             }
+            if (strcmp(OIC_JSON_CRL_NAME, rsrcName) && crlCborLen)
+            {
+                cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRL_NAME, strlen(OIC_JSON_CRL_NAME));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Name.");
+                cborEncoderResult |= cbor_encode_byte_string(&secRsrc, crlCbor, crlCborLen);
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Value.");
+            }
 
             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
@@ -405,6 +427,7 @@ exit:
     OICFree(credCbor);
     OICFree(pconfCbor);
     OICFree(resetPfCbor);
+    OICFree(crlCbor);
     return ret;
 }
 
index 198b62a..f4b6ecf 100644 (file)
@@ -40,9 +40,9 @@
 
 #define TAG "SRM-RM"
 
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) || defined(__WITH_TLS__)
 #include "crlresource.h"
-#endif // __WITH_X509__
+#endif // __WITH_X509__ || __WITH_TLS__
 
 OCStackResult SendSRMResponse(const OCEntityHandlerRequest *ehRequest,
         OCEntityHandlerResult ehRet, uint8_t *cborPayload, size_t size)
@@ -92,12 +92,12 @@ OCStackResult InitSecureResources( )
     {
         ret = InitCredResource();
     }
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) || defined(__WITH_TLS__)
     if(OC_STACK_OK == ret)
     {
         ret = InitCRLResource();
     }
-#endif // __WITH_X509__
+#endif // __WITH_X509__ || __WITH_TLS__
     if(OC_STACK_OK == ret)
     {
         ret = InitSVCResource();
@@ -134,9 +134,9 @@ OCStackResult DestroySecureResources( )
     DeInitCredResource();
     DeInitDoxmResource();
     DeInitPstatResource();
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) || defined(__WITH_TLS__)
     DeInitCRLResource();
-#endif // __WITH_X509__
+#endif // __WITH_X509__ || __WITH_TLS__
     DeInitSVCResource();
     DeInitAmaclResource();
 //#ifdef DIRECT_PAIRING
index c39d463..f9644d4 100644 (file)
@@ -32,7 +32,9 @@
 #include "securevirtualresourcetypes.h"
 #include "secureresourcemanager.h"
 #include "srmresourcestrings.h"
-
+#ifdef __WITH_TLS__
+#include "pkix_interface.h"
+#endif //__WITH_TLS__
 #define TAG  "SRM"
 
 #ifdef __WITH_X509__
@@ -325,12 +327,13 @@ OCStackResult SRMInitSecureResources()
     }
 #endif
 #ifdef __WITH_TLS__
-    if(CA_STATUS_OK != CAregisterTlsCredentialsHandler(GetDtlsPskCredentials))
+    if (CA_STATUS_OK != CAregisterTlsCredentialsHandler(GetDtlsPskCredentials))
     {
         OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
         ret = OC_STACK_ERROR;
     }
     CAregisterPkixInfoHandler(GetPkixInfo);
+    CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
 #endif
 #if defined(__WITH_X509__)
     CARegisterDTLSX509CredentialsHandler(GetDtlsX509Credentials);
@@ -373,6 +376,7 @@ bool SRMIsSecurityResourceURI(const char* uri)
         OIC_RSRC_PCONF_URI,
         OIC_RSRC_DPAIRING_URI,
         OIC_RSRC_VER_URI,
+        OC_RSRVD_PROV_CRL_URL
     };
 
     // Remove query from Uri for resource string comparison
index c05e529..4dcea24 100644 (file)
@@ -147,6 +147,7 @@ const char * OIC_JSON_SEC_V_NAME = "secv";
 const char * OIC_JSON_EMPTY_STRING = "";
 
 const char * TRUST_CA = "trust_ca";
+const char * PRIMARY_CERT = "primary_cert";
 
 OicUuid_t WILDCARD_SUBJECT_ID = {"*"};
 OicUuid_t WILDCARD_SUBJECT_B64_ID = { .id = {'2', '2', '2', '2', '2', '2', '2', '2',
index a301830..95ff3cb 100644 (file)
 #include <inttypes.h>
 #include "octypes.h"
 
+#ifdef __WITH_TLS__
+#include "securevirtualresourcetypes.h"
+#endif
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -137,6 +141,12 @@ bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OC
 bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value);
 bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value);
 
+#ifdef __WITH_TLS__
+bool OCRepPayloadSetPropPubDataType(OCRepPayload *payload, const char *name, const OicSecKey_t *value);
+bool OCRepPayloadSetPropPubDataTypeAsOwner(OCRepPayload *payload, const char *name, const OicSecKey_t *value);
+bool OCRepPayloadGetPropPubDataType(const OCRepPayload *payload, const char *name, OicSecKey_t *value);
+#endif
+
 /**
  * This function allocates memory for the byte string array and sets it in the payload.
  *
index 2bba4a1..aade6ad 100644 (file)
@@ -433,6 +433,118 @@ extern "C" {
 /** To represent grant type with refresh token. */
 #define OC_RSRVD_GRANT_TYPE_REFRESH_TOKEN  "refresh_token"
 
+/** Cloud CRL */
+#define OC_RSRVD_PROV_CRL_URL              "/oic/credprov/crl"
+
+#define OC_RSRVD_LAST_UPDATE              "lu"
+
+#define OC_RSRVD_THIS_UPDATE              "tu"
+
+#define OC_RSRVD_NEXT_UPDATE              "nu"
+
+#define OC_RSRVD_SERIAL_NUMBERS           "rcsn"
+
+#define OC_RSRVD_CRL                      "crl"
+
+#define OC_RSRVD_CRL_ID                   "crlid"
+
+/** Cloud ACL */
+#define OC_RSRVD_GROUP_URL                "/oic/group"
+
+#define OC_RSRVD_ACL_GROUP_URL            "/oic/acl/group"
+
+#define OC_RSRVD_ACL_INVITE_URL           "/oic/acl/invite"
+
+#define OC_RSRVD_ACL_VERIFY_URL           "/oic/acl/verify"
+
+#define OC_RSRVD_ACL_ID_URL               "/oic/acl/id"
+
+#define OC_RSRVD_MEMBER_ID                "mid"
+
+#define OC_RSRVD_GROUP_ID                 "gid"
+
+#define OC_RSRVD_OWNER_ID                 "oid"
+
+#define OC_RSRVD_ACL_ID                   "aclid"
+
+#define OC_RSRVD_ACE_ID                   "aceid"
+
+#define OC_RSRVD_DEVICE_ID                "di"
+
+#define OC_RSRVD_SUBJECT_ID               "sid"
+
+#define OC_RSRVD_REQUEST_METHOD           "rm"
+
+#define OC_RSRVD_REQUEST_URI              "uri"
+
+#define OC_RSRVD_GROUP_MASTER_ID          "gmid"
+
+#define OC_RSRVD_GROUP_TYPE               "gtype"
+
+#define OC_RSRVD_SUBJECT_TYPE             "stype"
+
+#define OC_RSRVD_GROUP_ID_LIST            "gidlist"
+
+#define OC_RSRVD_MEMBER_ID_LIST           "midlist"
+
+#define OC_RSRVD_DEVICE_ID_LIST           "dilist"
+
+#define OC_RSRVD_ACCESS_CONTROL_LIST      "aclist"
+
+#define OC_RSRVD_RESOURCES                "resources"
+
+#define OC_RSRVD_VALIDITY                 "validity"
+
+#define OC_RSRVD_PERIOD                   "period"
+
+#define OC_RSRVD_RECURRENCE               "recurrence"
+
+#define OC_RSRVD_INVITE                   "invite"
+
+#define OC_RSRVD_INVITED                  "invited"
+
+#define OC_RSRVD_ENCODING                 "encoding"
+
+#define OC_OIC_SEC                        "oic.sec"
+
+#define OC_RSRVD_BASE64                   "base64"
+
+#define OC_RSRVD_DER                      "der"
+
+#define OC_RSRVD_PEM                      "pem"
+
+#define OC_RSRVD_RAW                      "raw"
+
+#define OC_RSRVD_UNKNOWN                  "unknown"
+
+#define OC_RSRVD_DATA                     "data"
+
+#define OC_RSRVD_RESOURCE_OWNER_UUID      "rowneruuid"
+
+#define OC_RSRVD_SUBJECT_UUID             "subjectuuid"
+
+#define OC_RSRVD_PERMISSION_MASK          "permission"
+
+#define OC_RSRVD_GROUP_PERMISSION         "gp"
+
+#define OC_RSRVD_GROUP_ACL                "gacl"
+
+/** Certificete Sign Request */
+#define OC_RSRVD_PROV_CERT_URI            "/oic/credprov/cert"
+
+#define OC_RSRVD_CSR                      "csr"
+
+#define OC_RSRVD_CERT                     "cert"
+
+#define OC_RSRVD_CACERT                   "certchain"
+
+#define OC_RSRVD_TOKEN_TYPE               "tokentype"
+
+#define OC_RSRVD_EXPIRES_IN               "expiresin"
+
+#define OC_RSRVD_REDIRECT_URI             "redirecturi"
+
+#define OC_RSRVD_CERTIFICATE              "certificate"
 /**
  * Mark a parameter as unused. Used to prevent unused variable compiler warnings.
  * Used in three cases:
index 121d219..5f3a8c1 100644 (file)
@@ -35,6 +35,7 @@
 #include <inttypes.h>
 #include "rdpayload.h"
 #include "oic_malloc.h"
+#include "ocpayload.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -137,138 +138,116 @@ INLINE_API void OCLinksLog(const LogLevel level, const OCLinksPayload *links)
     }
 }
 #endif
-INLINE_API void OCPayloadLogRep(LogLevel level, OCRepPayload* payload)
+
+//forward declaration required because function below is recursive
+INLINE_API void OCPayloadLogRep(LogLevel level, OCRepPayload* payload);
+
+INLINE_API void OCPayloadLogRepValues(LogLevel level, OCRepPayloadValue* val)
 {
-    OIC_LOG(level, (PL_TAG), "Payload Type: Representation");
-    OCRepPayload* rep = payload;
-    int i = 1;
-    while(rep)
+    while(val)
     {
-        OIC_LOG_V(level, PL_TAG, "\tResource #%d", i);
-        if(rep->uri)
-        {
-            OIC_LOG_V(level, PL_TAG, "\tURI:%s", rep->uri);
-        }
-
-        OCStringLL* strll =  rep->types;
-        if(strll)
+        switch(val->type)
         {
-            OIC_LOG(level, PL_TAG, "\tResource Types:");
-            while(strll)
+            case OCREP_PROP_NULL:
+                OIC_LOG_V(level, PL_TAG, "%s: NULL", val->name);
+                break;
+            case OCREP_PROP_INT:
+                OIC_LOG_V(level, PL_TAG, "%s(int):%zd", val->name, val->i);
+                break;
+            case OCREP_PROP_DOUBLE:
+                OIC_LOG_V(level, PL_TAG, "%s(double):%f", val->name, val->d);
+                break;
+            case OCREP_PROP_BOOL:
+                OIC_LOG_V(level, PL_TAG, "%s(bool):%s", val->name, val->b ? "true" : "false");
+                break;
+            case OCREP_PROP_STRING:
+                OIC_LOG_V(level, PL_TAG, "%s(string):%s", val->name, val->str);
+                break;
+            case OCREP_PROP_BYTE_STRING:
+                OIC_LOG_V(level, PL_TAG, "%s(binary):", val->name);
+                OIC_LOG_BUFFER(level, PL_TAG, val->ocByteStr.bytes, val->ocByteStr.len);
+                break;
+            case OCREP_PROP_OBJECT:
+                OIC_LOG_V(level, PL_TAG, "%s(OCRep):%s", val->name, val->obj->uri);
+                OCPayloadLogRep(level, val->obj);
+                break;
+            case OCREP_PROP_ARRAY:
             {
-                OIC_LOG_V(level, PL_TAG, "\t\t%s", strll->value);
-                strll = strll->next;
-            }
-        }
+                size_t len = calcDimTotal(val->arr.dimensions);
 
-        strll =  rep->interfaces;
-        if(strll)
-        {
-            OIC_LOG(level, PL_TAG, "\tInterfaces:");
-            while(strll)
-            {
-                OIC_LOG_V(level, PL_TAG, "\t\t%s", strll->value);
-                strll = strll->next;
-            }
-        }
+                OIC_LOG_V(level, PL_TAG, "%s(array): length = %zu", val->name, len);
+
+                for (size_t i = 0; i < len; i++)
+                {
+                    OIC_LOG_V(level, PL_TAG, "%s[%zu]:", val->name, i);
+                    char *indent = (char *)"\t\t";
 
-        // TODO Finish Logging: Values
-        OCRepPayloadValue* val = rep->values;
-        OIC_LOG(level, PL_TAG, "\tValues:");
-        while(val)
-        {
-            switch(val->type)
-            {
-                case OCREP_PROP_NULL:
-                    OIC_LOG_V(level, PL_TAG, "\t\t%s: NULL", val->name);
-                    break;
-                case OCREP_PROP_INT:
-                    OIC_LOG_V(level, PL_TAG, "\t\t%s(int):%zd", val->name, val->i);
-                    break;
-                case OCREP_PROP_DOUBLE:
-                    OIC_LOG_V(level, PL_TAG, "\t\t%s(double):%f", val->name, val->d);
-                    break;
-                case OCREP_PROP_BOOL:
-                    OIC_LOG_V(level, PL_TAG, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");
-                    break;
-                case OCREP_PROP_STRING:
-                    OIC_LOG_V(level, PL_TAG, "\t\t%s(string):%s", val->name, val->str);
-                    break;
-                case OCREP_PROP_BYTE_STRING:
-                    OIC_LOG_V(level, PL_TAG, "\t\t%s(binary):", val->name);
-                    OIC_LOG_BUFFER(level, PL_TAG, val->ocByteStr.bytes, val->ocByteStr.len);
-                    break;
-                case OCREP_PROP_OBJECT:
-                    OIC_LOG_V(level, PL_TAG, "\t\t%s(OCRep):%s", val->name, val->obj->uri);
-                    OCPayloadLogRep(level, val->obj);
-                    break;
-                case OCREP_PROP_ARRAY:
                     switch(val->arr.type)
                     {
                         case OCREP_PROP_INT:
-                            OIC_LOG_V(level, PL_TAG, "\t\t%s(int array):%zu x %zu x %zu",
-                                    val->name,
-                                    val->arr.dimensions[0], val->arr.dimensions[1],
-                                    val->arr.dimensions[2]);
+                            OIC_LOG_V(level, PL_TAG, "%s%zd", indent, val->arr.iArray[i]);
                             break;
                         case OCREP_PROP_DOUBLE:
-                            OIC_LOG_V(level, PL_TAG, "\t\t%s(double array):%zu x %zu x %zu",
-                                    val->name,
-                                    val->arr.dimensions[0], val->arr.dimensions[1],
-                                    val->arr.dimensions[2]);
+                            OIC_LOG_V(level, PL_TAG, "%s%f", indent, val->arr.dArray[i]);
                             break;
                         case OCREP_PROP_BOOL:
-                            OIC_LOG_V(level, PL_TAG, "\t\t%s(bool array):%zu x %zu x %zu",
-                                    val->name,
-                                    val->arr.dimensions[0], val->arr.dimensions[1],
-                                    val->arr.dimensions[2]);
+                            OIC_LOG_V(level, PL_TAG, "%s%s", indent, val->arr.bArray[i] ? "true" : "false");
                             break;
                         case OCREP_PROP_STRING:
-                            OIC_LOG_V(level, PL_TAG, "\t\t%s(string array):%zu x %zu x %zu",
-                                    val->name,
-                                    val->arr.dimensions[0], val->arr.dimensions[1],
-                                    val->arr.dimensions[2]);
+                            OIC_LOG_V(level, PL_TAG, "%s%s", indent, val->arr.strArray[i]);
                             break;
                         case OCREP_PROP_BYTE_STRING:
-                            OIC_LOG_V(level, PL_TAG, "\t\t%s(byte array):%zu x %zu x %zu",
-                                    val->name,
-                                    val->arr.dimensions[0], val->arr.dimensions[1],
-                                    val->arr.dimensions[2]);
+                        {
+                            OCByteString* data = &val->arr.ocByteStrArray[i];
+                            OIC_LOG_V(level, PL_TAG, "%s binary string, it's len = %zu, bytes:", indent, data->len);
+                            OIC_LOG_BUFFER(level, PL_TAG, data->bytes, data->len);
+                        }
                             break;
                         case OCREP_PROP_OBJECT:
-                        {
-                            OIC_LOG_V(level, PL_TAG, "\t\t%s(OCRep array):%zu x %zu x %zu",
-                                    val->name,
-                                    val->arr.dimensions[0], val->arr.dimensions[1],
-                                    val->arr.dimensions[2]);
-
-                            size_t i = 0;
-                            if (val->arr.dimensions[0] > 0)
-                            {
-                                for (i = 0 ; i < val->arr.dimensions[0] ; i++)
-                                {
-                                    OCPayloadLogRep(level, val->arr.objArray[i]);
-                                }
-                            }
+                            OCPayloadLogRep(level, val->arr.objArray[i]);
                             break;
-                        }
+                        case OCREP_PROP_ARRAY: //Seems as nested arrays doesn't not supported in API
                         default:
-                            OIC_LOG_V(ERROR, PL_TAG, "\t\t%s <-- Unknown/unsupported array type!",
+                            OIC_LOG_V(ERROR, PL_TAG, "%s <-- Unknown/unsupported array type!",
                                     val->name);
                             break;
                     }
-                    break;
-                default:
-                    OIC_LOG_V(ERROR, PL_TAG, "\t\t%s <-- Unknown type!", val->name);
-                    break;
+                }
+                break;
             }
-            val = val -> next;
+            default:
+                OIC_LOG_V(ERROR, PL_TAG, "%s <-- Unknown type!", val->name);
+                break;
         }
+        val = val -> next;
+    }
+}
+
+INLINE_API void OCPayloadLogRep(LogLevel level, OCRepPayload* payload)
+{
+    OCRepPayload* rep = payload;
+    int i = 1;
+    while(rep)
+    {
+        OCStringLL* strll =  rep->types;
+        while(strll)
+        {
+            strll = strll->next;
+        }
+        strll =  rep->interfaces;
+        while(strll)
+        {
+            strll = strll->next;
+        }
+
+        // TODO Finish Logging: Values
+        OCRepPayloadValue* val = rep->values;
+
+        OCPayloadLogRepValues(level, val);
 
         ++i;
         rep = rep->next;
     }
-
 }
 
 INLINE_API void OCPayloadLogDiscovery(LogLevel level, OCDiscoveryPayload* payload)
index 80e9e06..2afac6f 100644 (file)
@@ -688,6 +688,153 @@ bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool
     return true;
 }
 
+#ifdef __WITH_TLS__
+static char *getStringFromEncodingType(OicEncodingType_t type)
+{
+    char *str = NULL;
+    switch (type)
+    {
+        case OIC_ENCODING_BASE64: str = OC_RSRVD_BASE64; break;
+        case OIC_ENCODING_DER: str = OC_RSRVD_DER; break;
+        case OIC_ENCODING_PEM: str = OC_RSRVD_PEM; break;
+        case OIC_ENCODING_RAW: str = OC_RSRVD_RAW; break;
+        default: str = OC_RSRVD_UNKNOWN; break;
+    }
+    char encoding[32];
+    snprintf(encoding, sizeof(encoding), "%s.%s.%s", OC_OIC_SEC, OC_RSRVD_ENCODING, str);
+
+    return OICStrdup(encoding);
+}
+
+bool OCRepPayloadSetPropPubDataTypeAsOwner(OCRepPayload *payload, const char *name,
+                                           const OicSecKey_t *value)
+{
+    if (!payload || !name || !value)
+    {
+        return false;
+    }
+
+    bool binary_field = false;
+    if (OIC_ENCODING_RAW == value->encoding || OIC_ENCODING_DER == value->encoding)
+    {
+        binary_field = true;
+    }
+
+    OCRepPayload *heplerPayload = OCRepPayloadCreate();
+    if (!heplerPayload)
+    {
+        return false;
+    }
+
+    char *encoding = getStringFromEncodingType(value->encoding);
+    if (!OCRepPayloadSetPropString(heplerPayload, OC_RSRVD_ENCODING, encoding))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't set %s", OC_RSRVD_ENCODING);
+    }
+
+    OCByteString val = {.bytes = value->data, .len = value->len};
+    if (binary_field)
+    {
+        if (!OCRepPayloadSetPropByteString(heplerPayload, OC_RSRVD_DATA, val))
+        {
+            OIC_LOG_V(ERROR, TAG, "Can't set %s", OC_RSRVD_DATA);
+        }
+    }
+    else
+    {
+        if (!OCRepPayloadSetPropString(heplerPayload, OC_RSRVD_DATA, (char *)val.bytes))
+        {
+            OIC_LOG_V(ERROR, TAG, "Can't set %s", OC_RSRVD_DATA);
+        }
+    }
+
+    if (!OCRepPayloadSetPropObject(payload, name, (const OCRepPayload *)heplerPayload))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't set %s", name);
+    }
+
+    OCRepPayloadDestroy(heplerPayload);
+    OICFree(encoding);
+
+    return true;
+}
+
+bool OCRepPayloadSetPropPubDataType(OCRepPayload *payload, const char *name,
+                                    const OicSecKey_t *value)
+{
+    return OCRepPayloadSetPropPubDataTypeAsOwner(payload, name, value);
+}
+
+static OicEncodingType_t getEncodingTypeFromString(char *encoding)
+{
+    OicEncodingType_t type = OIC_ENCODING_UNKNOW;
+
+    char *str = strrchr(encoding, '.');
+    if (NULL == str)
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't find . in %s", encoding);
+        return type;
+    }
+    str++; //go to encoding itself
+
+    if (0 == strcmp(str, OC_RSRVD_BASE64)) type = OIC_ENCODING_BASE64;
+    else if (0 == strcmp(str, OC_RSRVD_DER)) type = OIC_ENCODING_DER;
+    else if (0 == strcmp(str, OC_RSRVD_PEM)) type = OIC_ENCODING_PEM;
+    else if (0 == strcmp(str, OC_RSRVD_RAW)) type = OIC_ENCODING_RAW;
+
+    return type;
+}
+
+bool OCRepPayloadGetPropPubDataType(const OCRepPayload *payload, const char *name, OicSecKey_t *value)
+{
+    OCRepPayload *heplerPayload = NULL;
+    char *encoding = NULL;
+    OCByteString val;
+
+    if (!payload || !name || !value)
+    {
+        return false;
+    }
+
+    if (!OCRepPayloadGetPropObject(payload, name, &heplerPayload))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get object with name %s", name);
+        return false;
+    }
+
+    if (!OCRepPayloadGetPropString(heplerPayload, OC_RSRVD_ENCODING, &encoding))
+    {
+        OIC_LOG_V(ERROR, TAG, "Can't get %s", OC_RSRVD_ENCODING);
+    }
+    else
+    {
+        value->encoding = getEncodingTypeFromString(encoding);
+        OICFree(encoding);
+    }
+
+    if (!OCRepPayloadGetPropByteString(heplerPayload, OC_RSRVD_DATA, &val))
+    {
+        if (!OCRepPayloadGetPropString(heplerPayload, OC_RSRVD_DATA, (char **)&val.bytes))
+        {
+            OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_DATA);
+        }
+        else
+        {
+            value->data = val.bytes;
+            value->len  = strlen(val.bytes);
+        }
+    }
+    else
+    {
+        value->data = val.bytes;
+        value->len  = val.len;
+    }
+
+    OCRepPayloadDestroy(heplerPayload);
+    return true;
+}
+#endif
+
 bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OCRepPayload* value)
 {
     OCRepPayload* temp = OCRepPayloadClone(value);
index dcd6bd7..c8cc507 100644 (file)
@@ -681,6 +681,14 @@ INPUT                  = . \
                          ../../csdk/stack/include/internal/oicgroup.h \
                          ../../csdk/stack/include/internal/oickeepalive.h \
                          guides \
+                         ../../csdk/security/include \
+                         ../../csdk/security/include\internal \
+                         ../../csdk/security/provisioning/include \
+                         ../../csdk/security/provisioning/include/internal \
+                         ../../csdk/security/provisioning/include/oxm \
+                         ../../csdk/security/provisioning/include/cloud \
+                         ../../csdk/security/provisioning/sample/cloudAuth.h \
+                         ../../csdk/security/provisioning/sample/cloudWrapper.h \
                          ../../../service/easy-setup/inc \
                          ../../../service/easy-setup/enrollee/inc \
                          ../../../service/resource-directory/include \
index 6f14d86..103ecf6 100644 (file)
@@ -100,8 +100,8 @@ if target_os in ['android','linux']:
        if env.get('SECURED') == '1':
                easy_setup_env.AppendUnique(CPPPATH = [
                        env.get('SRC_DIR') + '/resource/csdk/security/provisioning/include',
-                       env.get('SRC_DIR') + '/resource/csdk/connectivity/api/',
                        env.get('SRC_DIR') + '/resource/csdk/security/include/internal',
+                       env.get('SRC_DIR') + '/resource/csdk/connectivity/api/',
                        env.get('SRC_DIR') + '/resource/csdk/security/provisioning/include/internal',
                        env.get('SRC_DIR') + '/resource/csdk/security/provisioning/include/oxm'])
                if env.get('WITH_TCP') == True: