Absent client's certificate CB 07/194507/1
authorOleksii Beketov <ol.beketov@samsung.com>
Wed, 7 Nov 2018 13:21:00 +0000 (15:21 +0200)
committerDoHyun Pyun <dh79.pyun@samsung.com>
Wed, 5 Dec 2018 06:36:17 +0000 (15:36 +0900)
Added callback to get user's confirmation
in case of absent client's certificate

https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/334
(cherry picked from commit 4fb53e4bd30ff8bb94642c27195eccbe5276d949)

Change-Id: Id7f597ef75721de7291725510767241f0e0c2d37
Signed-off-by: Oleksii Beketov <ol.beketov@samsung.com>
Signed-off-by: DoHyun Pyun <dh79.pyun@samsung.com>
resource/csdk/connectivity/api/casecurityinterface.h
resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c
resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp

index 736541d..166bba6 100644 (file)
@@ -33,6 +33,7 @@
 #endif //__WITH_DTLS__ or __WITH_TLS__
 #include "cacommon.h"
 #include "byte_array.h"
+#include "octypes.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -72,6 +73,8 @@ typedef enum
     CA_SSL_EKCB_DTLS = 1
 }CASslEkcbProtocol_t;
 
+typedef OCStackResult (*UserConfirmNoCertCallback)(void * ctx);
+
 /**
  * This internal callback is used by CA layer to
  * retrieve PSK credentials from SRM.
@@ -354,6 +357,8 @@ typedef void (*SslExportKeysCallback_t)(const unsigned char* masterSecret,
 CAResult_t CASetSslExportKeysCallback(SslExportKeysCallback_t exportKeysCb,
                                       CASslEkcbProtocol_t protocol, CASslEkcbRole_t role);
 
+void CAsetNoCertConfirmCallback(UserConfirmNoCertCallback noCertCallback);
+
 #endif //__WITH_TLS__ or __WITH_DTLS__
 
 
index 9b117cd..0f221c6 100644 (file)
@@ -36,6 +36,7 @@
 #include "ocrandom.h"
 #include "byte_array.h"
 #include "octhread.h"
+#include "octypes.h"
 #include "timer.h"
 
 
@@ -519,6 +520,16 @@ static CAgetCredentialTypesHandler g_getCredentialTypesCallback = NULL;
 static CAgetPkixInfoHandler g_getPkixInfoCallback = NULL;
 
 /**
+ * Function pointer to get user confirmation in case of client's certificate absence
+ */
+static UserConfirmNoCertCallback g_noCertConfirmCallback = NULL;
+
+/**
+ * Function pointer to get user confirmation in case of client's certificate absence
+ */
+static int g_noCertConfirmState = OC_STACK_METHOD_NOT_ALLOWED;
+
+/**
  * @var g_setupPkContextCallback
  *
  * @brief callback to setup PK context handler for H/W based Public Key Infrastructure
@@ -614,6 +625,13 @@ void CAsetCredentialTypesCallback(CAgetCredentialTypesHandler credTypesCallback)
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
 }
 
+void CAsetNoCertConfirmCallback(UserConfirmNoCertCallback noCertCallback)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    g_noCertConfirmCallback = noCertCallback;
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+}
+
 static int GetAdapterIndex(CATransportAdapter_t adapter)
 {
     switch (adapter)
@@ -2340,7 +2358,6 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
         return CA_STATUS_FAILED;
     }
 
-
     SslEndPoint_t * peer = GetSslPeer(&sep->endpoint);
     if (NULL == peer)
     {
@@ -2389,6 +2406,24 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
             ret = mbedtls_ssl_handshake_step(&peer->ssl);
         }
         uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
+        if (MBEDTLS_SSL_IS_SERVER == peer->ssl.conf->endpoint &&
+            MBEDTLS_X509_BADCERT_MISSING == flags)
+        {
+            if (OC_STACK_METHOD_NOT_ALLOWED == g_noCertConfirmState)
+            {
+                g_noCertConfirmState = g_noCertConfirmCallback(NULL);
+                if (OC_STACK_OK == g_noCertConfirmState)
+                {
+                    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Absent peer's cert: user confirmation received");
+                }
+                else if (OC_STACK_USER_DENIED_REQ == g_noCertConfirmState)
+                {
+                    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Absent peer's cert: user denial received");
+                    SSL_CHECK_FAIL(peer, MBEDTLS_SSL_ALERT_LEVEL_FATAL, "Handshake error", 1,
+                                   CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+                }
+            }
+        }
         if (0 != flags &&
            ((MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint) ||
             (MBEDTLS_SSL_IS_SERVER == peer->ssl.conf->endpoint && MBEDTLS_X509_BADCERT_MISSING != flags)))
@@ -2396,6 +2431,7 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
             OIC_LOG_BUFFER(ERROR, NET_SSL_TAG, (const uint8_t *) &flags, sizeof(flags));
             SSL_CHECK_FAIL(peer, flags, "Cert verification failed", 1,
                                                      CA_STATUS_FAILED, GetAlertCode(flags));
+
         }
         SSL_CHECK_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)
index 90ed672..55ce08c 100644 (file)
@@ -434,6 +434,36 @@ OCStackResult confirmCB(void * ctx)
     return OC_STACK_OK;
 }
 
+OCStackResult confirmNoCertCB(void * ctx)
+{
+    OC_UNUSED(ctx);
+    for (;;)
+    {
+        int userConfirm;
+
+        printf("   > Peer has no cert!\n");
+        printf("   > Press 1 for confirmation\n");
+        printf("   > Press 0 otherwise\n");
+
+        for (int ret=0; 1!=ret; )
+        {
+            ret = scanf("%d", &userConfirm);
+            for (; 0x20<=getchar(); );  // for removing overflow garbage
+                                        // '0x20<=code' is character region
+        }
+        if (1 == userConfirm)
+        {
+            break;
+        }
+        else if (0 == userConfirm)
+        {
+            return OC_STACK_USER_DENIED_REQ;
+        }
+        printf("   Entered Wrong Number. Please Enter Again\n");
+    }
+    return OC_STACK_OK;
+}
+
 FILE* server_fopen(const char *path, const char *mode)
 {
     (void)path;
@@ -477,6 +507,7 @@ int main(int argc, char **argv)
     OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink, NULL, NULL};
 
     SetUserConfirmCB(NULL, confirmCB);
+    CAsetNoCertConfirmCallback(confirmNoCertCB);
 
     OCRegisterPersistentStorageHandler(&ps);