*
******************************************************************/
+#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif // _GNU_SOURCE
#include <stddef.h>
+#include <stdint.h>
#include <stdbool.h>
#include "ca_adapter_net_ssl.h"
#include "cacommon.h"
+#include "caadapterutils.h"
+#include "cainterface.h"
#include "caipinterface.h"
#include "oic_malloc.h"
+#include "ocrandom.h"
#include "byte_array.h"
-#include "camutex.h"
+#include "octhread.h"
+#include "timer.h"
+
// headers required for mbed TLS
#include "mbedtls/platform.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/pkcs12.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/net.h"
#ifdef __WITH_DTLS__
#include "mbedtls/timing.h"
#include "mbedtls/ssl_cookie.h"
#endif
+#include "pkix_interface.h"
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
#include "mbedtls/debug.h"
#include "mbedtls/version.h"
#endif
* @def TLS_MSG_BUF_LEN
* @brief Buffer size for TLS record. A single TLS record may be up to 16384 octets in length
*/
-
+#if defined (__TIZENRT__)
+#define TLS_MSG_BUF_LEN (2048)
+#else
#define TLS_MSG_BUF_LEN (16384)
+#endif
+
/**
* @def PSK_LENGTH
* @brief PSK keys max length
*/
#define RANDOM_LEN (32)
/**
- * @def RANDOM_LEN
- * @brief PSK generated keyblock length
+ * @def SHA384_MAC_KEY_LENGTH
+ * @brief MAC key length for SHA384 cipher suites
+ */
+#define SHA384_MAC_KEY_LENGTH (48)
+/**
+ * @def SHA256_MAC_KEY_LENGTH
+ * @brief MAC key length for SHA256 cipher suites
+ */
+#define SHA256_MAC_KEY_LENGTH (32)
+/**
+ * @def CCM_MAC_KEY_LENGTH
+ * @brief MAC key length for CCM cipher suites
+ */
+#define CCM_MAC_KEY_LENGTH (0)
+/**
+ * @def AES256_KEY_LENGTH
+ * @brief key material length for AES256 cipher suites
+ */
+#define AES256_KEY_LENGTH (32)
+/**
+ * @def AES128_KEY_LENGTH
+ * @brief key material length for AES128 cipher suites
+ */
+#define AES128_KEY_LENGTH (16)
+/**
+ * @def GCM_IV_LENGTH
+ * @brief length of nonce for GCM cipher suites
+ */
+#define GCM_IV_LENGTH (12)
+/**
+ * @def CCM_IV_LENGTH
+ * @brief length of nonce for CCM cipher suites
+ */
+#define CCM_IV_LENGTH (4)
+/**
+ * @def CBC_IV_LENGTH
+ * @brief length of nonce for CBC cipher suites
+ */
+#define CBC_IV_LENGTH (0)
+
+/**
+ * @var RETRANSMISSION_TIME
+ * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
*/
-#define KEY_BLOCK_LEN (96)
+#define RETRANSMISSION_TIME 1
/**@def SSL_CLOSE_NOTIFY(peer, ret)
*
* @param[in] ret error code
* @param[in] str debug string
* @param[in] mutex ca mutex
- * @param[in] return error code
+ * @param[in] error if code does not equal to -1 returns error code
* @param[in] msg allert message
*/
#define SSL_CHECK_FAIL(peer, ret, str, mutex, error, msg) \
-if (0 != (ret) && MBEDTLS_ERR_SSL_WANT_READ != (int) (ret) && \
- MBEDTLS_ERR_SSL_WANT_WRITE != (int) (ret) && \
+if (0 != (ret) && MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY != (int) (ret) && \
MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED != (int) (ret) && \
- MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY != (int) (ret)) \
+ MBEDTLS_ERR_SSL_WANT_READ != (int) (ret) && \
+ MBEDTLS_ERR_SSL_WANT_WRITE != (int) (ret) && \
+ MBEDTLS_ERR_SSL_NON_FATAL != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_USER_CANCELED != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_NO_CERT != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_BAD_CERT != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY != (int) (ret) && \
+ MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL != (int) (ret)) \
{ \
OIC_LOG_V(ERROR, NET_SSL_TAG, "%s: -0x%x", (str), -(ret)); \
if ((int) MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE != (int) (ret) && \
- (int) MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO != (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)); \
} \
- if ((int) MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == (int) (ret) && \
- ((int) MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED == (peer)->ssl.in_msg[1] || \
- (int) MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR == (peer)->ssl.in_msg[1] || \
- (int) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE == (peer)->ssl.in_msg[1] || \
- (int) MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC == (peer)->ssl.in_msg[1])) \
- { \
- SSL_RES((peer), CA_DTLS_AUTHENTICATION_FAILURE); \
- } \
RemovePeerFromList(&(peer)->sep.endpoint); \
if (mutex) \
{ \
- ca_mutex_unlock(g_sslContextMutex); \
+ oc_mutex_unlock(g_sslContextMutex); \
+ } \
+ if ((int) MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO != (int)(ret)) \
+ { \
+ SSL_RES((peer), CA_DTLS_AUTHENTICATION_FAILURE); \
} \
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__); \
- return (error); \
+ if (-1 != (intptr_t)error) \
+ { \
+ return (error); \
+ } \
}
+
+/**@def CONF_SSL(clientConf, serverConf, fn, ...)
+ *
+ * Calls \a fn for \a clientConf and \a serverConf.
+ *
+ */
+#define CONF_SSL(clientConf, serverConf, fn, ...) do { \
+fn((clientConf), __VA_ARGS__); \
+fn((serverConf), __VA_ARGS__); \
+} while (0)
+
/** @def CHECK_MBEDTLS_RET(f, ...)
* A macro that checks \a f function return code
*
if (0 != ret) { \
OIC_LOG_V(ERROR, NET_SSL_TAG, "%s returned -0x%04x\n", __func__, -(ret)); \
goto exit; \
-} } while(0)
+} } while (0)
typedef enum
{
- ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA,
- ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
- ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256,
- ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
- ADAPTER_CIPHER_MAX
-} AdapterCipher_t;
+ SSL_RSA_WITH_AES_256_CBC_SHA256,
+ SSL_RSA_WITH_AES_128_GCM_SHA256,
+ SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ SSL_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ SSL_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ SSL_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ SSL_ECDHE_ECDSA_WITH_AES_128_CCM,
+ SSL_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ SSL_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ SSL_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ SSL_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ SSL_ECDH_ANON_WITH_AES_128_CBC_SHA256,
+ SSL_CIPHER_MAX
+} SslCipher_t;
typedef enum
{
ADAPTER_CURVE_MAX
} AdapterCurve_t;
-int tlsCipher[ADAPTER_CIPHER_MAX][2] =
+static const int tlsCipher[SSL_CIPHER_MAX][2] =
{
- {MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, 0},
+ {MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, 0},
+ {MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, 0},
+ {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+ {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0},
+ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
{MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, 0},
- {MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256, 0},
- {MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 0}
+ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, 0},
+ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 0},
+ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 0},
+ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 0},
+ {MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 0},
+ {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 0},
+ {MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256, 0}
};
-static int g_cipherSuitesList[ADAPTER_CIPHER_MAX];
+static int g_cipherSuitesList[SSL_CIPHER_MAX];
+
+static int g_ssl_ordered_default_hashes[] = {
+#if defined(MBEDTLS_SHA256_C)
+ MBEDTLS_MD_SHA256,
+ MBEDTLS_MD_SHA224,
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ MBEDTLS_MD_SHA1,
+#endif
+ MBEDTLS_MD_NONE
+};
mbedtls_ecp_group_id curve[ADAPTER_CURVE_MAX][2] =
{
return 0;
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
/**
* Pass a message to the OIC logger.
*
}
#endif
-#if defined(_WIN32)
+#if defined(_WIN32) || defined (__TIZENRT__)
/*
* Finds the first occurrence of the byte string s in byte string l.
*/
mbedtls_ssl_config serverTlsConf;
mbedtls_ssl_config clientDtlsConf;
mbedtls_ssl_config serverDtlsConf;
-#ifdef __WITH_DTLS__
- mbedtls_ssl_cookie_ctx cookie_ctx;
- mbedtls_timing_delay_context timer;
-#endif // __WITH_DTLS__
- AdapterCipher_t cipher;
+
+ SslCipher_t cipher;
SslCallbacks_t adapterCallbacks[MAX_SUPPORTED_ADAPTERS];
mbedtls_x509_crl crl;
bool cipherFlag[2];
int selectedCipher;
+#ifdef __WITH_DTLS__
+ mbedtls_ssl_cookie_ctx cookieCtx;
+ int timerId;
+#endif
} SslContext_t;
/**
*/
static SslContext_t * g_caSslContext = NULL;
+static SslExportKeysCallback_t gTlsExportKeysCallback = NULL;
+
+static SslExportKeysCallback_t gDtlsExportKeysCallback = NULL;
+
/**
* @var g_getCredentialsCallback
* @brief callback to get TLS credentials (same as for DTLS)
static CAgetPkixInfoHandler g_getPkixInfoCallback = NULL;
/**
+ * @var g_setupPkContextCallback
+ *
+ * @brief callback to setup PK context handler for H/W based Public Key Infrastructure
+ */
+static CAsetupPkContextHandler g_setupPkContextCallback = NULL;
+
+/**
* @var g_dtlsContextMutex
* @brief Mutex to synchronize access to g_caSslContext.
*/
-static ca_mutex g_sslContextMutex = NULL;
+static oc_mutex g_sslContextMutex = NULL;
/**
* @var g_sslCallback
static CAErrorCallback g_sslCallback = NULL;
/**
+ * Data structure for PeerCertCallback.
+ */
+typedef struct
+{
+ PeerCertCallback cb;
+ void *ctx;
+} PeerCertCallback_t;
+
+/**
+ * @var g_peerCertCallback
+ *
+ * @brief callback to utilize peer certificate information
+ */
+static PeerCertCallback_t g_peerCertCallback = {NULL, NULL};
+
+/**
+ * @var g_decryptBuffer
+ * @brief decrypt buffer which will be used for decryption
+ */
+static uint8_t *g_decryptBuffer = NULL;
+
+/**
* Data structure for holding the data to be received.
*/
typedef struct SslRecBuf
uint8_t master[MASTER_SECRET_LEN];
uint8_t random[2*RANDOM_LEN];
#ifdef __WITH_DTLS__
- mbedtls_ssl_cookie_ctx cookieCtx;
-#endif
-
+ mbedtls_timing_delay_context timer;
+#endif // __WITH_DTLS__
} SslEndPoint_t;
void CAsetPskCredentialsCallback(CAgetPskCredentialsHandler credCallback)
g_getPkixInfoCallback = infoCallback;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
+
+void CAsetSetupPkContextCallback(CAsetupPkContextHandler setupPkCtxCallback)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ g_setupPkContextCallback = setupPkCtxCallback;
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+}
+
void CAsetCredentialTypesCallback(CAgetCredentialTypesHandler credTypesCallback)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
return 0;
case CA_ADAPTER_TCP:
return 1;
+ case CA_ADAPTER_GATT_BTLE:
+ return 2;
default:
OIC_LOG(ERROR, NET_SSL_TAG, "Unsupported adapter");
return -1;
* @param[in] data message
* @param[in] dataLen message length
*
- * @return message length
+ * @return message length or -1 on error.
*/
static int SendCallBack(void * tep, const unsigned char * data, size_t dataLen)
{
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
- VERIFY_NON_NULL_RET(tep, NET_SSL_TAG, "secure endpoint is NULL", 0);
- VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "data is NULL", 0);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
+ VERIFY_NON_NULL_RET(tep, NET_SSL_TAG, "secure endpoint is NULL", -1);
+ VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "data is NULL", -1);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", -1);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Data len: %zu", dataLen);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Adapter: %u", ((SslEndPoint_t * )tep)->sep.endpoint.adapter);
+ ssize_t sentLen = 0;
int adapterIndex = GetAdapterIndex(((SslEndPoint_t * )tep)->sep.endpoint.adapter);
- if (0 == adapterIndex || 1 == adapterIndex)
+ if (0 <= adapterIndex && MAX_SUPPORTED_ADAPTERS > adapterIndex)
{
CAPacketSendCallback sendCallback = g_caSslContext->adapterCallbacks[adapterIndex].sendCallback;
- sendCallback(&(((SslEndPoint_t * )tep)->sep.endpoint), (const void *) data, (uint32_t) dataLen);
+ sentLen = sendCallback(&(((SslEndPoint_t * )tep)->sep.endpoint), (const void *) data, dataLen);
+ if (sentLen < 0)
+ {
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "sendCallback() is Failed(%zd)", sentLen);
+ return -1;
+ }
+ else if ((size_t)sentLen != dataLen)
+ {
+ OIC_LOG_V(DEBUG, NET_SSL_TAG,
+ "Packet was partially sent - total/sent/remained bytes : %zd/%zu/%lu",
+ sentLen, dataLen, (dataLen - sentLen));
+ }
}
else
{
OIC_LOG(ERROR, NET_SSL_TAG, "Unsupported adapter");
- dataLen = 0;
+ return -1;
}
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
- return dataLen;
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
+ return sentLen;
}
/**
* Read callback.
return (int)retLen;
}
+static int CASslExportKeysHandler(void *p_expkey,
+ const unsigned char *ms,
+ const unsigned char *kb,
+ size_t maclen,
+ size_t keylen,
+ size_t ivlen)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+
+ if (NULL == g_caSslContext)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "SSL Context is not initialized.");
+ return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ }
+ if (NULL == p_expkey)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Can not find the protocol information from 'p_expkey'.");
+ return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ }
+
+ CASslEkcbProtocol_t* protocol = (CASslEkcbProtocol_t*)p_expkey;
+
+ if (gTlsExportKeysCallback && CA_SSL_EKCB_TLS == (*protocol))
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "Invoking TLS export key callback.");
+ gTlsExportKeysCallback(ms, kb, maclen, keylen, ivlen);
+ }
+ else if (gDtlsExportKeysCallback && CA_SSL_EKCB_DTLS == (*protocol))
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "Invoking DTLS export key callback.");
+ gDtlsExportKeysCallback(ms, kb, maclen, keylen, ivlen);
+ }
+ else
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Failed to Invoke (D)TLS export key callback.");
+ return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ }
+
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ return 0;
+}
+
+CAResult_t CASetSslExportKeysCallback(SslExportKeysCallback_t exportKeysCb,
+ CASslEkcbProtocol_t protocol, CASslEkcbRole_t role)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ mbedtls_ssl_config* sslConf = NULL;
+ static CASslEkcbProtocol_t protocolCtx = CA_SSL_EKCB_TLS;
+
+ if (CA_SSL_EKCB_TLS != protocol && CA_SSL_EKCB_DTLS != protocol)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Invaild protocol.");
+ return CA_STATUS_INVALID_PARAM;
+ }
+ if (CA_SSL_EKCB_CLIENT != role && CA_SSL_EKCB_SERVER != role)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Invaild role.");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "TLS Export Key Callback Type : [%s] [%s]",
+ (CA_SSL_EKCB_TLS == protocol ? "TLS" : "DTLS"),
+ (CA_SSL_EKCB_CLIENT == role ? "Client" : "Server"));
+
+ oc_mutex_lock(g_sslContextMutex);
+ if (NULL == g_caSslContext)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "SSL Context is not initialized.");
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_NOT_INITIALIZED;
+ }
+
+ if (CA_SSL_EKCB_TLS == protocol)
+ {
+ gTlsExportKeysCallback = exportKeysCb;
+ if (CA_SSL_EKCB_CLIENT == role)
+ {
+ sslConf = &g_caSslContext->clientTlsConf;
+ }
+ else
+ {
+ sslConf = &g_caSslContext->serverTlsConf;
+ }
+ }
+ else
+ {
+ gDtlsExportKeysCallback = exportKeysCb;
+ if (CA_SSL_EKCB_CLIENT == role)
+ {
+ sslConf = &g_caSslContext->clientDtlsConf;
+ }
+ else
+ {
+ sslConf = &g_caSslContext->serverDtlsConf;
+ }
+ }
+ protocolCtx = protocol;
+
+ if (NULL == exportKeysCb)
+ {
+ mbedtls_ssl_conf_export_keys_cb(sslConf, NULL, NULL);
+ OIC_LOG(DEBUG, NET_SSL_TAG, "Export key callback unregistered.");
+ }
+ else
+ {
+ mbedtls_ssl_conf_export_keys_cb(sslConf, CASslExportKeysHandler, (void*)(&protocolCtx));
+ OIC_LOG(DEBUG, NET_SSL_TAG, "Export key callback registered.");
+ }
+ oc_mutex_unlock(g_sslContextMutex);
+
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+
+ return CA_STATUS_OK;
+}
+
/**
* Parse chain of X.509 certificates.
*
* @param[out] crt container for X.509 certificates
* @param[in] data buffer with X.509 certificates. Certificates may be in either in PEM
- or DER format in a jumble. Each PEM certificate must be NULL-terminated.
+ or DER format in a jumble, delimiting symbols does not matter.
* @param[in] bufLen buffer length
+ * @param[in] errNum number certificates that failed to parse
*
- * @return 0 on success, -1 on error
+ * @return number of successfully parsed certificates or -1 on error
*/
-static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int bufLen)
+static int ParseChain(mbedtls_x509_crt * crt, unsigned char * buf, size_t bufLen, int * errNum)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(crt, NET_SSL_TAG, "Param crt is NULL" , -1);
VERIFY_NON_NULL_RET(buf, NET_SSL_TAG, "Param buf is NULL" , -1);
- int pos = 0;
- int ret = 0;
- size_t len = 0;
- unsigned char * tmp = NULL;
-
char pemCertHeader[] = {
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52,
0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
size_t pemCertHeaderLen = sizeof(pemCertHeader);
size_t pemCertFooterLen = sizeof(pemCertFooter);
+ size_t len = 0;
+ unsigned char * tmp = NULL;
+ int count = 0;
+ int ret = 0;
+ size_t pos = 0;
+
+ *errNum = 0;
while (pos < bufLen)
{
if (buf[pos] == 0x30 && buf[pos + 1] == 0x82)
CHECK_MBEDTLS_RET(mbedtls_asn1_get_len, &tmp, buf + bufLen, &len);
if (pos + len < bufLen)
{
- CHECK_MBEDTLS_RET(mbedtls_x509_crt_parse_der, crt, buf + pos, len + 4);
+ ret = mbedtls_x509_crt_parse_der(crt, buf + pos, len + 4);
+ if (0 == ret)
+ {
+ count++;
+ }
+ else
+ {
+ (*errNum)++;
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse_der returned -0x%04x\n", -(ret));
+ }
}
pos += len + 4;
}
- else if (0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen))
+ else if ((buf + pos + pemCertHeaderLen < buf + bufLen) &&
+ (0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen)))
{
void * endPos = NULL;
endPos = memmem(&(buf[pos]), bufLen - pos, pemCertFooter, pemCertFooterLen);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return -1;
}
- if ((*((char*)endPos + pemCertFooterLen + 0) == 0x0d) &&
- (*((char*)endPos + pemCertFooterLen + 1) == 0x0a) &&
- (*((char*)endPos + pemCertFooterLen + 2) == 0x00))
- {
- len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen + 3;
- }
- else if ((*((char*)endPos + pemCertFooterLen + 0) == 0x0a) &&
- (*((char*)endPos + pemCertFooterLen + 1) == 0x00))
+ len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen;
+ if (pos + len + 1 <= bufLen)
{
- len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen + 2;
+ char con = buf[pos + len];
+ buf[pos + len] = 0x00;
+ ret = mbedtls_x509_crt_parse(crt, buf + pos, len + 1);
+ if (0 == ret)
+ {
+ count++;
+ }
+ else
+ {
+ (*errNum)++;
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse returned -0x%04x\n", -(ret));
+ }
+ buf[pos + len] = con;
}
else
{
- OIC_LOG_V(ERROR, NET_SSL_TAG, "Incorrect PEM certificate ending");
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
- return -1;
+ unsigned char * lastCert = (unsigned char *)OICMalloc((len + 1) * sizeof(unsigned char));
+ memcpy(lastCert, buf + pos, len);
+ lastCert[len] = 0x00;
+ ret = mbedtls_x509_crt_parse(crt, lastCert, len + 1);
+ if (0 == ret)
+ {
+ count++;
+ }
+ else
+ {
+ (*errNum)++;
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse returned -0x%04x\n", -(ret));
+ }
+ OICFree(lastCert);
}
- CHECK_MBEDTLS_RET(mbedtls_x509_crt_parse, crt, buf + pos, len);
pos += len;
}
else
{
- OIC_LOG_BUFFER(DEBUG, NET_SSL_TAG, buf, bufLen);
- OIC_LOG_V(ERROR, NET_SSL_TAG, "parseChain returned -0x%x", -ret);
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
- return -1;
+ pos++;
}
}
+ OIC_LOG_V(INFO, NET_SSL_TAG, "%s successfully parsed %d certificates", __func__, count);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
- return 0;
+ return count;
exit:
return -1;
}
+static int VerifyCertificateCallback(void *p_vrfy, mbedtls_x509_crt *crt, int depth,
+ uint32_t *flags)
+{
+ (void)p_vrfy;
+ char buf[1024] = {0};
+
+ if (0 != *flags) // Invalid Cerificate
+ {
+ int ret;
+ ret = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
+ if (0 < ret)
+ {
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "%s(%d)", buf, *flags);
+ }
+ return 1;
+ }
+
+ if (NULL == g_peerCertCallback.cb)
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "NOT SET g_peerCertCallback");
+ return 0;
+ }
+
+ /*
+ * e.g.
+ * depth = 0 : Own Cert.
+ * depth = 1 : Sub CA Cert.
+ * depth = 2 : Root CA Cert.
+ */
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Depth : %d", depth);
+
+ mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "crt : %s", buf);
+
+ g_peerCertCallback.cb(g_peerCertCallback.ctx, crt, depth);
+
+ return 0;
+}
+
+CAResult_t CAsetPeerCertCallback(void *ctx, PeerCertCallback peerCertCallback)
+{
+#ifndef __WITH_DTLS__
+ UNUSED(ctx);
+ UNUSED(peerCertCallback);
+ OIC_LOG(ERROR, NET_SSL_TAG, "Not Supported");
+ return CA_NOT_SUPPORTED;
+#endif
+
+ if (peerCertCallback)
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "SET peerCertCallback");
+ g_peerCertCallback.cb = peerCertCallback;
+ g_peerCertCallback.ctx = ctx;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "UNSET peerCertCallback");
+ g_peerCertCallback.cb = NULL;
+ g_peerCertCallback.ctx = NULL;
+ }
+ return CA_STATUS_OK;
+}
+
//Loads PKIX related information from SRM
static int InitPKIX(CATransportAdapter_t adapter)
{
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(g_getPkixInfoCallback, NET_SSL_TAG, "PKIX info callback is NULL", -1);
- g_getPkixInfoCallback(&g_pkiInfo);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", -1);
mbedtls_x509_crt_free(&g_caSslContext->ca);
mbedtls_x509_crt_free(&g_caSslContext->crt);
mbedtls_pk_init(&g_caSslContext->pkey);
mbedtls_x509_crl_init(&g_caSslContext->crl);
- mbedtls_ssl_config * serverConf = (adapter == CA_ADAPTER_IP ?
+ mbedtls_ssl_config * serverConf = (adapter == CA_ADAPTER_IP ||
+ adapter == CA_ADAPTER_GATT_BTLE ?
&g_caSslContext->serverDtlsConf : &g_caSslContext->serverTlsConf);
- mbedtls_ssl_config * clientConf = (adapter == CA_ADAPTER_IP ?
+ mbedtls_ssl_config * clientConf = (adapter == CA_ADAPTER_IP ||
+ adapter == CA_ADAPTER_GATT_BTLE ?
&g_caSslContext->clientDtlsConf : &g_caSslContext->clientTlsConf);
- // optional
- int ret = ParseChain(&g_caSslContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len);
- if (0 != ret)
+
+#ifdef __WITH_DTLS__
+ /*
+ * Conf. is initialized in CAinitSslAdapter()
+ */
+ mbedtls_ssl_conf_verify(&g_caSslContext->clientDtlsConf, VerifyCertificateCallback, NULL);
+#endif
+
+ // load pk key, cert, trust chain and crl
+ if (g_getPkixInfoCallback)
+ {
+ OIC_LOG(INFO, NET_SSL_TAG, "g_getPkixInfoCallback will be invoked");
+ g_getPkixInfoCallback(&g_pkiInfo);
+ }
+
+ // parse own certficate (optional)
+ int ret;
+ int errNum;
+ int count = ParseChain(&g_caSslContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len, &errNum);
+ if (0 >= count)
{
OIC_LOG(WARNING, NET_SSL_TAG, "Own certificate chain parsing error");
goto required;
}
- ret = mbedtls_pk_parse_key(&g_caSslContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
- NULL, 0);
+ if (0 != errNum)
+ {
+ OIC_LOG_V(WARNING, NET_SSL_TAG, "Own certificate chain parsing error: %d certs failed to parse", errNum);
+ goto required;
+ }
+
+ // parse private key if hw is not supported (optional)
+ if(NULL == g_setupPkContextCallback)
+ {
+ OIC_LOG(INFO, NET_SSL_TAG, "g_setupPkContextCallback is NULL");
+ ret = mbedtls_pk_parse_key(&g_caSslContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
+ NULL, 0);
+ }
+ else
+ {
+ OIC_LOG(INFO, NET_SSL_TAG, "g_setupPkContextCallback will be invoked");
+ // setup hw pk context (optional)
+ ret = g_setupPkContextCallback(&g_caSslContext->pkey);
+ if (0 == ret)
+ {
+ // setup public parameter
+ mbedtls_pk_type_t ktype = mbedtls_pk_get_type(&g_caSslContext->pkey);
+ if (MBEDTLS_PK_ECKEY == ktype || MBEDTLS_PK_ECKEY_DH == ktype
+ || MBEDTLS_PK_ECDSA == ktype)
+ {
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Copy ecp public param from cert, keytype [%d]", ktype);
+ mbedtls_ecp_keypair *eckey = (mbedtls_ecp_keypair*)g_caSslContext->crt.pk.pk_ctx;
+ mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context*)g_caSslContext->pkey.pk_ctx;
+ if (ecdsa && eckey)
+ {
+ ret = mbedtls_ecdsa_from_keypair(ecdsa, eckey);
+ if(0 != ret )
+ {
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "Fail to copy public param [0x%x]", ret);
+ }
+ }
+ else
+ {
+ OIC_LOG_V(WARNING, NET_SSL_TAG, "key-ctx(%p), cert-ctx(%p)", ecdsa, eckey);
+ goto required;
+ }
+ }
+ else
+ {
+ OIC_LOG_V(INFO, NET_SSL_TAG, "loaded key is not one of eckey type [%d]", ktype);
+ }
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "Fail to call g_setupPkContextCallback [%d]", ret);
+ }
+ }
if (0 != ret)
{
OIC_LOG(WARNING, NET_SSL_TAG, "Key parsing error");
}
required:
- ret = ParseChain(&g_caSslContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len);
- if(0 != ret)
+ count = ParseChain(&g_caSslContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len, &errNum);
+ if(0 >= count)
{
- OIC_LOG(ERROR, NET_SSL_TAG, "CA chain parsing error");
+ OIC_LOG(WARNING, NET_SSL_TAG, "CA chain in svr db was not parsed");
+ OIC_LOG(WARNING, NET_SSL_TAG, " but if working as server, chain not required");
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return -1;
}
+ if(0 != errNum)
+ {
+ OIC_LOG_V(WARNING, NET_SSL_TAG, "CA chain parsing warning: %d certs failed to parse", errNum);
+ }
ret = mbedtls_x509_crl_parse_der(&g_caSslContext->crl, g_pkiInfo.crl.data, g_pkiInfo.crl.len);
if(0 != ret)
{
- OIC_LOG(WARNING, NET_SSL_TAG, "CRL parsing error");
- mbedtls_ssl_conf_ca_chain(clientConf, &g_caSslContext->ca, NULL);
- mbedtls_ssl_conf_ca_chain(serverConf, &g_caSslContext->ca, NULL);
+ OIC_LOG(WARNING, NET_SSL_TAG, "CRL in svr db was not parsed");
+ CONF_SSL(clientConf, serverConf, mbedtls_ssl_conf_ca_chain, &g_caSslContext->ca, NULL);
}
else
{
- mbedtls_ssl_conf_ca_chain(clientConf, &g_caSslContext->ca, &g_caSslContext->crl);
- mbedtls_ssl_conf_ca_chain(serverConf, &g_caSslContext->ca, &g_caSslContext->crl);
+ CONF_SSL(clientConf, serverConf, mbedtls_ssl_conf_ca_chain,
+ &g_caSslContext->ca, &g_caSslContext->crl);
}
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
return 0;
}
OIC_LOG_V(WARNING, NET_SSL_TAG, "Out %s", __func__);
return -1;
}
+
/**
* Gets session corresponding for endpoint.
*
uint32_t listLength = 0;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(peer, NET_SSL_TAG, "TLS peer is NULL", NULL);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
SslEndPoint_t *tep = NULL;
listLength = u_arraylist_length(g_caSslContext->peerList);
{
continue;
}
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Compare [%s:%d] and [%s:%d]",
- peer->addr, peer->port, tep->sep.endpoint.addr, tep->sep.endpoint.port);
- if((0 == strncmp(peer->addr, tep->sep.endpoint.addr, MAX_ADDR_STR_SIZE_CA))
- && (peer->port == tep->sep.endpoint.port))
+
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Compare [%s:%d] and [%s:%d] for %d adapter",
+ peer->addr, peer->port, tep->sep.endpoint.addr, tep->sep.endpoint.port,
+ peer->adapter);
+
+ if((peer->adapter == tep->sep.endpoint.adapter)
+ && (0 == strncmp(peer->addr, tep->sep.endpoint.addr, MAX_ADDR_STR_SIZE_CA))
+ && (peer->port == tep->sep.endpoint.port || CA_ADAPTER_GATT_BTLE == peer->adapter))
{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Found Peer:[%s:%d] for %d adapter",
+ peer->addr, peer->port, peer->adapter);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return tep;
}
}
- OIC_LOG(DEBUG, NET_SSL_TAG, "Return NULL");
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Peer not found:[%s:%d] for %d adapter",
+ peer->addr, peer->port, peer->adapter);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return NULL;
}
-#ifdef _ENABLE_MULTIPLE_OWNER_
-/**
- * Gets CA secure endpoint info corresponding for endpoint.
- *
- * @param[in] peer remote address
- *
- * @return CASecureEndpoint or NULL
- */
-const CASecureEndpoint_t *GetCASecureEndpointData(const CAEndpoint_t* peer)
+bool CAIsExistSslPeer(const CAEndpoint_t *peer)
{
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ oc_mutex_lock(g_sslContextMutex);
+ if (NULL == g_caSslContext)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+ oc_mutex_unlock(g_sslContextMutex);
+ return false;
+ }
+
+ if (GetSslPeer(peer))
+ {
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Exist Peer");
+ oc_mutex_unlock(g_sslContextMutex);
+ return true;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Not Exist Peer");
+ oc_mutex_unlock(g_sslContextMutex);
+ return false;
+ }
+}
+
+/**
+ * Gets session corresponding for endpoint.
+ *
+ * @param[in] peer remote address
+ *
+ * @return TLS session or NULL
+ */
+static SslEndPoint_t *GetSslPeerUsingUuid(const uint8_t *identity, size_t idLength)
+{
+ uint32_t listIndex = 0;
+ uint32_t listLength = 0;
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ VERIFY_NON_NULL_RET(identity, NET_SSL_TAG, "Param identity is NULL", NULL);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
+
+ OIC_LOG(INFO, NET_SSL_TAG, "[Target UUID]");
+ OIC_LOG_BUFFER(INFO, NET_SSL_TAG, identity, idLength);
+
+ SslEndPoint_t *tep = NULL;
+ listLength = u_arraylist_length(g_caSslContext->peerList);
+ for (listIndex = 0; listIndex < listLength; listIndex++)
+ {
+ tep = (SslEndPoint_t *) u_arraylist_get(g_caSslContext->peerList, listIndex);
+ if (NULL == tep)
+ {
+ continue;
+ }
+
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Compare UUID for [%s:%d]",
+ tep->sep.endpoint.addr, tep->sep.endpoint.port);
+
+ if ((tep->sep.identity.id_length == idLength)
+ && (0 == memcmp(identity, tep->sep.identity.id, idLength)))
+ {
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Found matched UUID in [%s:%d]",
+ tep->sep.endpoint.addr, tep->sep.endpoint.port);
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ return tep;
+ }
+ }
+ OIC_LOG(INFO, NET_SSL_TAG, "Peer not found");
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ return NULL;
+}
+
+
+#ifdef MULTIPLE_OWNER
+/**
+ * Gets CA secure endpoint info corresponding for endpoint.
+ *
+ * @param[in] peer remote address
+ *
+ * @return CASecureEndpoint or NULL
+ */
+const CASecureEndpoint_t *GetCASecureEndpointData(const CAEndpoint_t* peer)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
// TODO: Added as workaround, need to debug
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return NULL;
}
if(sslPeer)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return &sslPeer->sep;
}
OIC_LOG(DEBUG, NET_SSL_TAG, "Return NULL");
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return NULL;
}
#endif
VERIFY_NON_NULL_VOID(tep, NET_SSL_TAG, "tep");
mbedtls_ssl_free(&tep->ssl);
-#ifdef __WITH_DTLS__
- mbedtls_ssl_cookie_free(&tep->cookieCtx);
-#endif
DeleteCacheList(tep->cacheList);
OICFree(tep);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
*
* @param[in] endpoint remote address
*/
-static void RemovePeerFromList(CAEndpoint_t * endpoint)
+static void RemovePeerFromList(const CAEndpoint_t * endpoint)
{
- uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ VERIFY_NON_NULL_VOID(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL");
VERIFY_NON_NULL_VOID(endpoint, NET_SSL_TAG, "endpoint");
+ uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
{
SslEndPoint_t * tep = (SslEndPoint_t *)u_arraylist_get(g_caSslContext->peerList,listIndex);
continue;
}
if(0 == strncmp(endpoint->addr, tep->sep.endpoint.addr, MAX_ADDR_STR_SIZE_CA)
- && (endpoint->port == tep->sep.endpoint.port))
+ && (endpoint->port == tep->sep.endpoint.port || CA_ADAPTER_GATT_BTLE == endpoint->adapter))
{
u_arraylist_remove(g_caSslContext->peerList, listIndex);
DeleteSslEndPoint(tep);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Remove Peer:[%s:%d] for %d adapter",
+ endpoint->addr, endpoint->port, endpoint->adapter);
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return;
}
}
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Peer not found:[%s:%d] for %d adapter",
+ endpoint->addr, endpoint->port, endpoint->adapter);
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
/**
* Deletes session list.
*/
static void DeletePeerList()
{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "%s", __func__);
+ VERIFY_NON_NULL_VOID(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL");
+
uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
{
{
continue;
}
+ if (MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
+ {
+ int ret = 0;
+ do
+ {
+ ret = mbedtls_ssl_close_notify(&tep->ssl);
+ }
+ while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);
+ }
DeleteSslEndPoint(tep);
}
u_arraylist_free(&g_caSslContext->peerList);
CAResult_t CAcloseSslConnection(const CAEndpoint_t *endpoint)
{
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "Param endpoint is NULL" , CA_STATUS_INVALID_PARAM);
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
SslEndPoint_t * tep = GetSslPeer(endpoint);
if (NULL == tep)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Session does not exist");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+ /* No error checking, the connection might be closed already */
+ int ret = 0;
+ do
+ {
+ ret = mbedtls_ssl_close_notify(&tep->ssl);
+ }
+ while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);
+
+ RemovePeerFromList(&tep->sep.endpoint);
+ oc_mutex_unlock(g_sslContextMutex);
+
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAcloseSslConnectionUsingUuid(const uint8_t *identity, size_t idLength)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ VERIFY_NON_NULL_RET(identity, NET_SSL_TAG, "Param identity is NULL" , CA_STATUS_INVALID_PARAM);
+
+ oc_mutex_lock(g_sslContextMutex);
+ if (NULL == g_caSslContext)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ SslEndPoint_t* tep = GetSslPeerUsingUuid(identity, idLength);
+ if (NULL == tep)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Session does not exist");
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
+
/* No error checking, the connection might be closed already */
int ret = 0;
do
while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);
RemovePeerFromList(&tep->sep.endpoint);
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_OK;
}
-void CAcloseSslConnectionAll()
+void CAcloseSslConnectionAll(CATransportAdapter_t transportType)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return;
}
uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
+ OIC_LOG_V(INFO, NET_SSL_TAG,
+ "Required transport [%d], peer count [%d]", transportType, listLength);
for (uint32_t i = listLength; i > 0; i--)
{
- SslEndPoint_t *tep = (SslEndPoint_t *)u_arraylist_remove(g_caSslContext->peerList, i - 1);
+ SslEndPoint_t *tep = (SslEndPoint_t *)u_arraylist_get(g_caSslContext->peerList, i - 1);
if (NULL == tep)
{
continue;
}
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "SSL Connection [%s:%d]",
- tep->sep.endpoint.addr, tep->sep.endpoint.port);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "SSL Connection [%s:%d], Transport [%d]",
+ tep->sep.endpoint.addr, tep->sep.endpoint.port, tep->sep.endpoint.adapter);
+
+ // check transport matching
+ if (0 == (tep->sep.endpoint.adapter & transportType))
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "Skip the un-matched transport session");
+ continue;
+ }
// TODO: need to check below code after socket close is ensured.
/*int ret = 0;
}
while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);*/
+ // delete from list
+ u_arraylist_remove(g_caSslContext->peerList, i - 1);
DeleteSslEndPoint(tep);
}
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return;
static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl_config * config)
{
SslEndPoint_t * tep = NULL;
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "endpoint", NULL);
VERIFY_NON_NULL_RET(config, NET_SSL_TAG, "config", NULL);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
tep = (SslEndPoint_t *) OICCalloc(1, sizeof (SslEndPoint_t));
if (NULL == tep)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Setup failed");
OICFree(tep);
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
return NULL;
}
mbedtls_ssl_set_bio(&tep->ssl, tep, SendCallBack, RecvCallBack, NULL);
if (MBEDTLS_SSL_TRANSPORT_DATAGRAM == config->transport)
{
- mbedtls_ssl_set_timer_cb(&tep->ssl, &g_caSslContext->timer,
+ mbedtls_ssl_set_timer_cb(&tep->ssl, &tep->timer,
mbedtls_timing_set_delay, mbedtls_timing_get_delay);
if (MBEDTLS_SSL_IS_SERVER == config->endpoint)
{
- if (0 != mbedtls_ssl_cookie_setup(&tep->cookieCtx, mbedtls_ctr_drbg_random,
- &g_caSslContext->rnd))
- {
- OIC_LOG(ERROR, NET_SSL_TAG, "Cookie setup failed!");
- OICFree(tep);
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
- return NULL;
- }
- mbedtls_ssl_conf_dtls_cookies(config, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
- &tep->cookieCtx);
if (0 != mbedtls_ssl_set_client_transport_id(&tep->ssl,
(const unsigned char *) endpoint->addr, sizeof(endpoint->addr)))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Transport id setup failed!");
+ mbedtls_ssl_free(&tep->ssl);
OICFree(tep);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return NULL;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return NULL;
}
+ OIC_LOG_V(INFO, NET_SSL_TAG, "New [%s role] endpoint added [%s:%d]",
+ (MBEDTLS_SSL_IS_SERVER==config->endpoint ? "server" : "client"),
+ endpoint->addr, endpoint->port);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return tep;
}
*/
static int InitPskIdentity(mbedtls_ssl_config * config)
{
+ uint8_t keyBuf[PSK_LENGTH] = {0};
uint8_t idBuf[UUID_LENGTH] = {0};
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(config, NET_SSL_TAG, "Param config is NULL" , -1);
+ //Retrieve PSK identity from SVR DB
if (0 > g_getCredentialsCallback(CA_DTLS_PSK_IDENTITY, NULL, 0, idBuf, UUID_LENGTH))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Identity not found");
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return -1;
}
- if (0 != mbedtls_ssl_conf_psk(config, idBuf, 0, idBuf, UUID_LENGTH))
+ //Store PSK ideneity in mbedtls_ssl_config
+ if (0 != mbedtls_ssl_conf_psk(config, keyBuf, PSK_LENGTH, idBuf, UUID_LENGTH))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Identity initialization failed!");
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
{
int index = 0;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
- if (NULL == g_getCredentialTypesCallback)
- {
- OIC_LOG(ERROR, NET_SSL_TAG, "Param callback is null");
- return;
- }
+ VERIFY_NON_NULL_VOID(config, NET_SSL_TAG, "Invaild param");
+ VERIFY_NON_NULL_VOID(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL");
+ VERIFY_NON_NULL_VOID(g_getCredentialTypesCallback, NET_SSL_TAG, "Param callback is null");
+
+ //Resetting cipherFlag
+ g_caSslContext->cipherFlag[0] = false;
+ g_caSslContext->cipherFlag[1] = false;
g_getCredentialTypesCallback(g_caSslContext->cipherFlag);
// Retrieve the PSK credential from SRM
- // PIN OTM if (true == g_caSslContext->cipherFlag[0] && 0 != InitPskIdentity(config))
if (0 != InitPskIdentity(config))
{
OIC_LOG(ERROR, NET_SSL_TAG, "PSK identity initialization failed!");
}
- // Retrieve the ECC credential from SRM
- if (true == g_caSslContext->cipherFlag[1] || ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA == g_caSslContext->cipher)
+ // Retrieve the Cert credential from SRM
+ if (true == g_caSslContext->cipherFlag[1])
{
int ret = InitPKIX(adapter);
if (0 != ret)
}
memset(g_cipherSuitesList, 0, sizeof(g_cipherSuitesList));
- if (ADAPTER_CIPHER_MAX != g_caSslContext->cipher)
+
+ // Add the preferred ciphersuite first
+ if (SSL_CIPHER_MAX != g_caSslContext->cipher)
{
g_cipherSuitesList[index] = tlsCipher[g_caSslContext->cipher][0];
- index ++;
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Preferred ciphersuite added");
+ index++;
+ }
+
+ // Add PSK ciphersuite
+ if (true == g_caSslContext->cipherFlag[0] &&
+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 != tlsCipher[g_caSslContext->cipher][0])
+ {
+ g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+ OIC_LOG(DEBUG, NET_SSL_TAG, "PSK ciphersuite added");
+ index++;
}
+
+ // Add all certificate ciphersuites
if (true == g_caSslContext->cipherFlag[1])
{
- g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
- index ++;
+ for (unsigned int i = 0; i < SSL_CIPHER_MAX - 1; i++)
+ {
+ if (MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 != tlsCipher[i][0] &&
+ i != g_caSslContext->cipher)
+ {
+ g_cipherSuitesList[index] = tlsCipher[i][0];
+ index ++;
+ }
+ }
+
+ if (MBEDTLS_SSL_IS_SERVER == config->endpoint)
+ {
+ mbedtls_ssl_conf_authmode(config, MBEDTLS_SSL_VERIFY_OPTIONAL);
+ }
}
- if (true == g_caSslContext->cipherFlag[0])
+
+ OIC_LOG(INFO, NET_SSL_TAG, "Supported ciphersuites:");
+ for (int i = 0; i < index; i++)
{
- g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Ciphersuite %04x", g_cipherSuitesList[i]);
}
mbedtls_ssl_conf_ciphersuites(config, g_cipherSuitesList);
int ret = 0;
SslEndPoint_t * tep = NULL;
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "Param endpoint is NULL" , NULL);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
+ //Remove previous peer info from peer list.
+ RemovePeerFromList(endpoint);
- mbedtls_ssl_config * config = (endpoint->adapter == CA_ADAPTER_IP ?
+ mbedtls_ssl_config * config = (endpoint->adapter == CA_ADAPTER_IP ||
+ endpoint->adapter == CA_ADAPTER_GATT_BTLE ?
&g_caSslContext->clientDtlsConf : &g_caSslContext->clientTlsConf);
tep = NewSslEndPoint(endpoint, config);
if (NULL == tep)
//Load allowed SVR suites from SVR DB
SetupCipher(config, endpoint->adapter);
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Add %s:%d", tep->sep.endpoint.addr, tep->sep.endpoint.port);
ret = u_arraylist_add(g_caSslContext->peerList, (void *) tep);
if (!ret)
{
{
break;
}
+ else if (-1 == ret)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Handshake failed due to socket error");
+ RemovePeerFromList(&tep->sep.endpoint);
+ return NULL;
+ }
SSL_CHECK_FAIL(tep, ret, "Handshake error", 0, NULL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
}
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
return tep;
}
-
+#ifdef __WITH_DTLS__
+/**
+ * Stops DTLS retransmission.
+ */
+static void StopRetransmit()
+{
+ if (g_caSslContext)
+ {
+ unregisterTimer(g_caSslContext->timerId);
+ g_caSslContext->timerId= -1;
+ }
+}
+#endif
void CAdeinitSslAdapter()
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_VOID(g_sslContextMutex, NET_SSL_TAG, "context mutex is NULL");
//Lock tlsContext mutex
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
// Clear all lists
DeletePeerList();
// De-initialize mbedTLS
+ mbedtls_x509_crt_free(&g_caSslContext->ca);
mbedtls_x509_crt_free(&g_caSslContext->crt);
mbedtls_pk_free(&g_caSslContext->pkey);
+ mbedtls_x509_crl_free(&g_caSslContext->crl);
#ifdef __WITH_TLS__
mbedtls_ssl_config_free(&g_caSslContext->clientTlsConf);
mbedtls_ssl_config_free(&g_caSslContext->serverTlsConf);
#ifdef __WITH_DTLS__
mbedtls_ssl_config_free(&g_caSslContext->clientDtlsConf);
mbedtls_ssl_config_free(&g_caSslContext->serverDtlsConf);
+ mbedtls_ssl_cookie_free(&g_caSslContext->cookieCtx);
#endif // __WITH_DTLS__
mbedtls_ctr_drbg_free(&g_caSslContext->rnd);
mbedtls_entropy_free(&g_caSslContext->entropy);
-
+#ifdef __WITH_DTLS__
+ StopRetransmit();
+#endif
// De-initialize tls Context
OICFree(g_caSslContext);
g_caSslContext = NULL;
+ // Delete decrypt buffer
+ if (g_decryptBuffer)
+ {
+ OICFree(g_decryptBuffer);
+ g_decryptBuffer = NULL;
+ }
+
// Unlock tlsContext mutex and de-initialize it
- ca_mutex_unlock(g_sslContextMutex);
- ca_mutex_free(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
+ oc_mutex_free(g_sslContextMutex);
g_sslContextMutex = NULL;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s ", __func__);
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(conf, NET_SSL_TAG, "Param conf is NULL" , -1);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", -1);
mbedtls_ssl_config_init(conf);
if (mbedtls_ssl_config_defaults(conf, mode, transport, MBEDTLS_SSL_PRESET_DEFAULT) != 0)
{
mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_renegotiation(conf, MBEDTLS_SSL_RENEGOTIATION_DISABLED);
mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+ mbedtls_ssl_conf_sig_hashes(conf, g_ssl_ordered_default_hashes);
-#ifndef NDEBUG
+#ifdef __WITH_DTLS__
+ if (MBEDTLS_SSL_TRANSPORT_DATAGRAM == transport &&
+ MBEDTLS_SSL_IS_SERVER == mode)
+ {
+ mbedtls_ssl_conf_dtls_cookies(conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
+ &g_caSslContext->cookieCtx);
+ }
+#endif // __WITH_DTLS__
+
+#if !defined(NDEBUG) || defined(TB_LOG)
mbedtls_ssl_conf_dbg(conf, DebugSsl, NULL);
mbedtls_debug_set_threshold(MBED_TLS_DEBUG_LEVEL);
#endif
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return 0;
}
+#ifdef __WITH_DTLS__
+/**
+ * Starts DTLS retransmission.
+ */
+static int StartRetransmit()
+{
+ uint32_t listIndex = 0;
+ uint32_t listLength = 0;
+ SslEndPoint_t *tep = NULL;
+
+ oc_mutex_lock(g_sslContextMutex);
+ if (NULL == g_caSslContext)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL. Stop retransmission");
+ oc_mutex_unlock(g_sslContextMutex);
+ return -1;
+ }
+ if (g_caSslContext->timerId != -1)
+ {
+ //clear previous timer
+ unregisterTimer(g_caSslContext->timerId);
+
+ listLength = u_arraylist_length(g_caSslContext->peerList);
+
+ for (listIndex = 0; listIndex < listLength; listIndex++)
+ {
+ tep = (SslEndPoint_t *) u_arraylist_get(g_caSslContext->peerList, listIndex);
+ if (NULL == tep
+ || (tep->ssl.conf && MBEDTLS_SSL_TRANSPORT_STREAM == tep->ssl.conf->transport)
+ || MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
+ {
+ continue;
+ }
+ OIC_LOG_V(INFO, NET_SSL_TAG, "peer #%d", (int) listIndex);
+
+ int ret = mbedtls_ssl_handshake_step(&tep->ssl);
+
+ if (MBEDTLS_ERR_SSL_CONN_EOF != ret)
+ {
+ //start new timer
+ registerTimer(RETRANSMISSION_TIME, &g_caSslContext->timerId, (void *) StartRetransmit);
+ //unlock & return
+ SSL_CHECK_FAIL(tep, ret, "Retransmission", 1, CA_STATUS_FAILED,
+ MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+ }
+ }
+ }
+ //start new timer
+ registerTimer(RETRANSMISSION_TIME, &g_caSslContext->timerId, (void *) StartRetransmit);
+ oc_mutex_unlock(g_sslContextMutex);
+
+ return 0;
+}
+#endif
CAResult_t CAinitSslAdapter()
{
// Initialize mutex for tlsContext
if (NULL == g_sslContextMutex)
{
- g_sslContextMutex = ca_mutex_new();
+ g_sslContextMutex = oc_mutex_new();
VERIFY_NON_NULL_RET(g_sslContextMutex, NET_SSL_TAG, "malloc failed", CA_MEMORY_ALLOC_FAILED);
}
else
}
// Lock tlsContext mutex and create tlsContext
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
g_caSslContext = (SslContext_t *)OICCalloc(1, sizeof(SslContext_t));
if (NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context malloc failed");
- ca_mutex_unlock(g_sslContextMutex);
- ca_mutex_free(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
+ oc_mutex_free(g_sslContextMutex);
g_sslContextMutex = NULL;
return CA_MEMORY_ALLOC_FAILED;
}
OIC_LOG(ERROR, NET_SSL_TAG, "peerList initialization failed!");
OICFree(g_caSslContext);
g_caSslContext = NULL;
- ca_mutex_unlock(g_sslContextMutex);
- ca_mutex_free(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
+ oc_mutex_free(g_sslContextMutex);
g_sslContextMutex = NULL;
return CA_STATUS_FAILED;
}
/* Initialize TLS library
*/
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
char version[MBED_TLS_VERSION_LEN];
mbedtls_version_get_string(version);
OIC_LOG_V(INFO, NET_SSL_TAG, "mbed TLS version: %s", version);
if(urandomFd == -1)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Fails open /dev/urandom!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
CAdeinitSslAdapter();
return CA_STATUS_FAILED;
}
{
OIC_LOG(ERROR, NET_SSL_TAG, "Fails read from /dev/urandom!");
close(urandomFd);
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
CAdeinitSslAdapter();
return CA_STATUS_FAILED;
}
&g_caSslContext->entropy, seed, sizeof(SEED)))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Seed initialization failed!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
CAdeinitSslAdapter();
return CA_STATUS_FAILED;
}
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_IS_CLIENT))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Client config initialization failed!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
CAdeinitSslAdapter();
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_FAILED;
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_IS_SERVER))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Server config initialization failed!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
CAdeinitSslAdapter();
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_FAILED;
}
#endif // __WITH_TLS__
#ifdef __WITH_DTLS__
+ mbedtls_ssl_cookie_init(&g_caSslContext->cookieCtx);
+ if (0 != mbedtls_ssl_cookie_setup(&g_caSslContext->cookieCtx, mbedtls_ctr_drbg_random,
+ &g_caSslContext->rnd))
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Cookie setup failed!");
+ oc_mutex_unlock(g_sslContextMutex);
+ CAdeinitSslAdapter();
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ return CA_STATUS_FAILED;
+ }
+
if (0 != InitConfig(&g_caSslContext->clientDtlsConf,
MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_IS_CLIENT))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Client config initialization failed!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
CAdeinitSslAdapter();
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_FAILED;
MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_IS_SERVER))
{
OIC_LOG(ERROR, NET_SSL_TAG, "Server config initialization failed!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
CAdeinitSslAdapter();
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_FAILED;
#endif // __WITH_DTLS__
// set default cipher
- g_caSslContext->cipher = ADAPTER_CIPHER_MAX;
+ g_caSslContext->cipher = SSL_CIPHER_MAX;
// init X.509
mbedtls_x509_crt_init(&g_caSslContext->ca);
mbedtls_pk_init(&g_caSslContext->pkey);
mbedtls_x509_crl_init(&g_caSslContext->crl);
- ca_mutex_unlock(g_sslContextMutex);
+#ifdef __WITH_DTLS__
+ g_caSslContext->timerId = -1;
+#endif
+
+ // create decrypt buffer
+ g_decryptBuffer = (uint8_t *)OICCalloc(1, TLS_MSG_BUF_LEN);
+ if (NULL == g_decryptBuffer)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Decrypt buffer malloc failed");
+ oc_mutex_unlock(g_sslContextMutex);
+ CAdeinitSslAdapter();
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ oc_mutex_unlock(g_sslContextMutex);
+#ifdef __WITH_DTLS__
+ StartRetransmit();
+#endif
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_OK;
{
int ret = 0;
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s ", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "In %s ", __func__);
VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG,"Remote address is NULL", CA_STATUS_INVALID_PARAM);
VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "Data is NULL", CA_STATUS_INVALID_PARAM);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Data to be encrypted dataLen [%d]", dataLen);
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if(NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
if (NULL == tep)
{
OIC_LOG(ERROR, NET_SSL_TAG, "TLS handshake failed");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
if (MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
{
- ret = mbedtls_ssl_write(&tep->ssl, (unsigned char *) data, dataLen);
+ OIC_LOG(INFO, NET_SSL_TAG, "(MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)");
- if(ret < 0)
+ unsigned char *dataBuf = (unsigned char *)data;
+ size_t written = 0;
+
+ do
{
- OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedTLS write returned %d", ret);
- RemovePeerFromList(&tep->sep.endpoint);
- ca_mutex_unlock(g_sslContextMutex);
- return CA_STATUS_FAILED;
- }
+ ret = mbedtls_ssl_write(&tep->ssl, dataBuf, dataLen - written);
+ if (ret < 0)
+ {
+ if (MBEDTLS_ERR_SSL_WANT_WRITE != ret)
+ {
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedTLS write failed! returned 0x%x", -ret);
+ RemovePeerFromList(&tep->sep.endpoint);
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+ continue;
+ }
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "mbedTLS write returned with sent bytes[%d]", ret);
+
+ dataBuf += ret;
+ written += ret;
+ } while (dataLen > written);
+
}
else
{
if (NULL == msg || !u_arraylist_add(tep->cacheList, (void *) msg))
{
OIC_LOG(ERROR, NET_SSL_TAG, "u_arraylist_add failed!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
}
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_OK;
}
/**
SslCacheMessage_t * msg = (SslCacheMessage_t *) u_arraylist_get(tep->cacheList, listIndex);
if (NULL != msg && NULL != msg->data && 0 != msg->len)
{
+ unsigned char *dataBuf = (unsigned char *)msg->data;
+ size_t written = 0;
+
do
{
- ret = mbedtls_ssl_write(&tep->ssl, (unsigned char *) msg->data, msg->len);
- }
- while(MBEDTLS_ERR_SSL_WANT_WRITE == ret);
+ ret = mbedtls_ssl_write(&tep->ssl, dataBuf, msg->len - written);
+ if (ret < 0)
+ {
+ if (MBEDTLS_ERR_SSL_WANT_WRITE != ret)
+ {
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedTLS write failed! returned -0x%x", -ret);
+ break;
+ }
+ continue;
+ }
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "mbedTLS write returned with sent bytes[%d]", ret);
+
+ dataBuf += ret;
+ written += ret;
+ } while (msg->len > written);
- if(ret < 0)
- {
- OIC_LOG_V(ERROR, NET_SSL_TAG,"mbedTLS write returned %d", ret );
- }
if (u_arraylist_remove(tep->cacheList, listIndex))
{
DeleteCacheMessage(msg);
g_sslCallback = tlsHandshakeCallback;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
-// TODO move ConvertStrToUuid function to common module
-/*
- * Converts string UUID to CARemoteId_t
- *
- * @param strUuid Device UUID in string format
- * @param uuid converted UUID in CARemoteId_t format
- *
- * @return 0 for success.
- * */
-static int ConvertStrToUuid(const char* strUuid, CARemoteId_t* uuid)
-{
- if(NULL == strUuid || NULL == uuid)
- {
- OIC_LOG(ERROR, NET_SSL_TAG, "ConvertStrToUuid : Invalid param");
- return -1;
- }
-
- size_t urnIdx = 0;
- size_t uuidIdx = 0;
- size_t strUuidLen = 0;
- char convertedUuid[UUID_LENGTH * 2] = {0};
-
- strUuidLen = strlen(strUuid);
- if(0 == strUuidLen)
- {
- OIC_LOG(INFO, NET_SSL_TAG, "The empty string detected, The UUID will be converted to "\
- "\"00000000-0000-0000-0000-000000000000\"");
- }
- else if(UUID_LENGTH * 2 + 4 == strUuidLen)
- {
- for(uuidIdx=0, urnIdx=0; uuidIdx < UUID_LENGTH ; uuidIdx++, urnIdx+=2)
- {
- if(*(strUuid + urnIdx) == '-')
- {
- urnIdx++;
- }
- sscanf(strUuid + urnIdx, "%2hhx", &convertedUuid[uuidIdx]);
- }
- }
- else
- {
- OIC_LOG(ERROR, NET_SSL_TAG, "Invalid string uuid format");
- return -1;
- }
-
- memcpy(uuid->id, convertedUuid, UUID_LENGTH);
- uuid->id_length = UUID_LENGTH;
- return 0;
-}
/* Read data from TLS connection
*/
CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t dataLen)
{
int ret = 0;
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(sep, NET_SSL_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "Param data is NULL" , CA_STATUS_INVALID_PARAM);
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
SslEndPoint_t * peer = GetSslPeer(&sep->endpoint);
if (NULL == peer)
{
- mbedtls_ssl_config * config = (sep->endpoint.adapter == CA_ADAPTER_IP ?
+ mbedtls_ssl_config * config = (sep->endpoint.adapter == CA_ADAPTER_IP ||
+ sep->endpoint.adapter == CA_ADAPTER_GATT_BTLE ?
&g_caSslContext->serverDtlsConf : &g_caSslContext->serverTlsConf);
peer = NewSslEndPoint(&sep->endpoint, config);
if (NULL == peer)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Malloc failed!");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
//Load allowed TLS suites from SVR DB
{
OIC_LOG(ERROR, NET_SSL_TAG, "u_arraylist_add failed!");
OICFree(peer);
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
}
sizeof(sep->endpoint.addr));
ret = mbedtls_ssl_handshake_step(&peer->ssl);
}
- uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
- if (0 != flags)
+ if (MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint)
{
- 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));
+ uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
+ if (0 != flags)
+ {
+ 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)
SendCacheMessages(peer);
}
- if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caSslContext->selectedCipher ||
- MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA == g_caSslContext->selectedCipher)
+ int selectedCipher = peer->ssl.session->ciphersuite;
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "(D)TLS Session is connected via ciphersuite [0x%x]", selectedCipher);
+ if (MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 != selectedCipher &&
+ MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256 != 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);
- SSL_CHECK_FAIL(peer, ret, "Failed to retrieve cert", 1,
- CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_NO_CERT);
- uuidPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
- UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
-
- if (NULL != uuidPos)
+ //SSL_CHECK_FAIL(peer, ret, "Failed to retrieve cert", 1,
+ // CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_NO_CERT);
+ if (0 == ret)
{
- memcpy(uuid, (char*) uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
- ret = ConvertStrToUuid(uuid, &peer->sep.identity);
- SSL_CHECK_FAIL(peer, ret, "Failed to convert subject", 1,
+ uuidPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
+ UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
+
+ if (NULL != uuidPos)
+ {
+ memcpy(uuid, (char*) uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "certificate uuid string: %s" , uuid);
+ ret = OCConvertStringToUuid(uuid, peer->sep.identity.id);
+ SSL_CHECK_FAIL(peer, ret, "Failed to convert subject", 1,
+ CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
+ }
+ else
+ {
+ OIC_LOG(WARNING, NET_SSL_TAG, "uuid not found");
+ }
+
+ userIdPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
+ USERID_PREFIX, sizeof(USERID_PREFIX) - 1);
+ if (NULL != userIdPos)
+ {
+ memcpy(uuid, (char*) userIdPos + sizeof(USERID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
+ ret = OCConvertStringToUuid(uuid, peer->sep.userId.id);
+ SSL_CHECK_FAIL(peer, ret, "Failed to convert subject alt name", 1,
CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
+ }
+ else
+ {
+ OIC_LOG(WARNING, NET_SSL_TAG, "Subject alternative name not found");
+ }
}
- else
- {
- OIC_LOG(WARNING, NET_SSL_TAG, "uuid not found");
- }
+ }
- userIdPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
- USERID_PREFIX, sizeof(USERID_PREFIX) - 1);
- if (NULL != userIdPos)
- {
- memcpy(uuid, (char*) userIdPos + sizeof(USERID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
- ret = ConvertStrToUuid(uuid, &peer->sep.userId);
- SSL_CHECK_FAIL(peer, ret, "Failed to convert subject alt name", 1,
- CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
- }
- else
- {
- OIC_LOG(WARNING, NET_SSL_TAG, "Subject alternative name not found");
- }
+ if (MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint)
+ {
+ SendCacheMessages(peer);
}
+ mbedtls_ssl_config * config = (sep->endpoint.adapter == CA_ADAPTER_IP ||
+ sep->endpoint.adapter == CA_ADAPTER_GATT_BTLE ?
+ &g_caSslContext->serverDtlsConf : &g_caSslContext->serverTlsConf);
- ca_mutex_unlock(g_sslContextMutex);
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ mbedtls_ssl_conf_authmode(config, MBEDTLS_SSL_VERIFY_REQUIRED);
+
+ oc_mutex_unlock(g_sslContextMutex);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_OK;
}
}
if (MBEDTLS_SSL_HANDSHAKE_OVER == peer->ssl.state)
{
- uint8_t decryptBuffer[TLS_MSG_BUF_LEN] = {0};
+ OIC_LOG(INFO, NET_SSL_TAG, "(MBEDTLS_SSL_HANDSHAKE_OVER == peer->ssl.state)");
+
+ // flag to read again remained data
+ bool read_more = false;
do
{
- ret = mbedtls_ssl_read(&peer->ssl, decryptBuffer, TLS_MSG_BUF_LEN);
- } while (MBEDTLS_ERR_SSL_WANT_READ == ret);
-
- if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret ||
- // TinyDTLS sends fatal close_notify alert
- (MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == ret &&
- MBEDTLS_SSL_ALERT_LEVEL_FATAL == peer->ssl.in_msg[0] &&
- MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY == peer->ssl.in_msg[1]))
- {
- OIC_LOG(INFO, NET_SSL_TAG, "Connection was closed gracefully");
- SSL_CLOSE_NOTIFY(peer, ret);
- RemovePeerFromList(&peer->sep.endpoint);
- ca_mutex_unlock(g_sslContextMutex);
- return CA_STATUS_OK;
- }
+ if (NULL == g_decryptBuffer)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "decrypt buffer is NULL");
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+ memset(g_decryptBuffer, 0, TLS_MSG_BUF_LEN);
+ read_more = false;
- if (0 > ret)
- {
- OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_ssl_read returned -0x%x", -ret);
- //SSL_RES(peer, CA_STATUS_FAILED);
- RemovePeerFromList(&peer->sep.endpoint);
- ca_mutex_unlock(g_sslContextMutex);
- return CA_STATUS_FAILED;
- }
- int adapterIndex = GetAdapterIndex(peer->sep.endpoint.adapter);
- if (0 == adapterIndex || adapterIndex == 1)
- {
- g_caSslContext->adapterCallbacks[adapterIndex].recvCallback(&peer->sep, decryptBuffer, ret);
- }
- else
- {
- OIC_LOG(ERROR, NET_SSL_TAG, "Unsuported adapter");
- RemovePeerFromList(&peer->sep.endpoint);
- ca_mutex_unlock(g_sslContextMutex);
- return CA_STATUS_FAILED;
- }
+ do
+ {
+ ret = mbedtls_ssl_read(&peer->ssl, g_decryptBuffer, TLS_MSG_BUF_LEN);
+ } while (MBEDTLS_ERR_SSL_WANT_READ == ret);
+
+ if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret ||
+ // TinyDTLS sends fatal close_notify alert
+ (MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == ret &&
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL == peer->ssl.in_msg[0] &&
+ MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY == peer->ssl.in_msg[1]))
+ {
+ OIC_LOG(INFO, NET_SSL_TAG, "Connection was closed gracefully");
+ RemovePeerFromList(&peer->sep.endpoint);
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_OK;
+ }
+
+ if (0 > ret)
+ {
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_ssl_read returned -0x%x", -ret);
+ //SSL_RES(peer, CA_STATUS_FAILED);
+ RemovePeerFromList(&peer->sep.endpoint);
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+ else if (0 < ret)
+ {
+ int adapterIndex = GetAdapterIndex(peer->sep.endpoint.adapter);
+ if (0 <= adapterIndex && MAX_SUPPORTED_ADAPTERS > adapterIndex)
+ {
+ CAResult_t res;
+ res = g_caSslContext->adapterCallbacks[adapterIndex].recvCallback(&peer->sep,
+ g_decryptBuffer, ret);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "recvCallback is failed");
+ RemovePeerFromList(&peer->sep.endpoint);
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ // check if decrypted data is remained in stream transport
+ size_t remained = mbedtls_ssl_get_bytes_avail(&peer->ssl);
+ if (0 < remained &&
+ MBEDTLS_SSL_TRANSPORT_STREAM == peer->ssl.conf->transport)
+ {
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "need to read %zu bytes more", remained);
+ read_more = true;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Unsuported adapter");
+ RemovePeerFromList(&peer->sep.endpoint);
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+ }
+ } while (read_more);
}
- ca_mutex_unlock(g_sslContextMutex);
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ oc_mutex_unlock(g_sslContextMutex);
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_OK;
}
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_VOID(sendCallback, NET_SSL_TAG, "sendCallback is NULL");
VERIFY_NON_NULL_VOID(recvCallback, NET_SSL_TAG, "recvCallback is NULL");
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
return;
}
-// if (MAX_SUPPORTED_ADAPTERS > type)
+ switch (type)
{
- switch (type)
- {
- case CA_ADAPTER_IP:
- g_caSslContext->adapterCallbacks[0].recvCallback = recvCallback;
- g_caSslContext->adapterCallbacks[0].sendCallback = sendCallback;
- break;
- case CA_ADAPTER_TCP:
- g_caSslContext->adapterCallbacks[1].recvCallback = recvCallback;
- g_caSslContext->adapterCallbacks[1].sendCallback = sendCallback;
- break;
- default:
- OIC_LOG_V(ERROR, NET_SSL_TAG, "Unsupported adapter: %d", type);
- }
+ case CA_ADAPTER_IP:
+ g_caSslContext->adapterCallbacks[0].recvCallback = recvCallback;
+ g_caSslContext->adapterCallbacks[0].sendCallback = sendCallback;
+ break;
+ case CA_ADAPTER_TCP:
+ g_caSslContext->adapterCallbacks[1].recvCallback = recvCallback;
+ g_caSslContext->adapterCallbacks[1].sendCallback = sendCallback;
+ break;
+ case CA_ADAPTER_GATT_BTLE:
+ g_caSslContext->adapterCallbacks[2].recvCallback = recvCallback;
+ g_caSslContext->adapterCallbacks[2].sendCallback = sendCallback;
+ break;
+ default:
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "Unsupported adapter: %d", type);
}
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
+/**
+ * Gets index of the TLS ciphersuite in the SslCipher_t enum.
+ *
+ * @param[in] cipher TLS chiphersuite code
+ *
+ * @return corresponding enum
+ */
-CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
+static SslCipher_t GetCipherIndex(const uint32_t cipher)
{
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
- VERIFY_NON_NULL_RET(g_getCredentialTypesCallback, NET_SSL_TAG, "Param callback is null", CA_STATUS_FAILED);
- g_getCredentialTypesCallback(g_caSslContext->cipherFlag);
switch(cipher)
{
- case MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA:
+ case MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256:
{
-#ifdef __WITH_TLS__
- //todo check that Cred with RSA cert exists
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
- tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
- tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
-#endif
-#ifdef __WITH_DTLS__
- //todo check that Cred with RSA cert exists
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
- tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
- tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
-#endif
- g_caSslContext->cipher = ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA;
- break;
+ return SSL_RSA_WITH_AES_256_CBC_SHA256;
+ }
+ case MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256:
+ {
+ return SSL_RSA_WITH_AES_128_GCM_SHA256;
+ }
+ case MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ {
+ return SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+ }
+ case MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ {
+ return SSL_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+ }
+ case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ {
+ return SSL_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
}
case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
{
- if (false == g_caSslContext->cipherFlag[1])
- {
- OIC_LOG(ERROR, NET_SSL_TAG, "No Credential for ECC");
- return CA_STATUS_FAILED;
- }
-#ifdef __WITH_TLS__
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
-#endif
-#ifdef __WITH_DTLS__
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
-#endif
- g_caSslContext->cipher = ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
- break;
+ return SSL_ECDHE_ECDSA_WITH_AES_128_CCM_8;
}
- case MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256:
+ case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
{
-#ifdef __WITH_TLS__
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
- tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
- tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
-#endif
-#ifdef __WITH_DTLS__
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
- tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
- tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
-#endif
- g_caSslContext->cipher = ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256;
- break;
+ return SSL_ECDHE_ECDSA_WITH_AES_128_CCM;
+ }
+ case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ {
+ return SSL_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+ }
+ case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+ {
+ return SSL_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+ }
+ case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ {
+ return SSL_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
}
case MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
{
-#if 0 // PIN OTM
- if (false == g_caSslContext->cipherFlag[0])
- {
- OIC_LOG(ERROR, NET_SSL_TAG, "No Credential for PSK");
- return CA_STATUS_FAILED;
- }
-#endif
-#ifdef __WITH_TLS__
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
-#endif
-#ifdef __WITH_DTLS__
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
- mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
- tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
-#endif
- g_caSslContext->cipher = ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
- break;
+ return SSL_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+ }
+ case MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ {
+ return SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+ }
+ case MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256:
+ {
+ return SSL_ECDH_ANON_WITH_AES_128_CBC_SHA256;
}
default:
{
- OIC_LOG(ERROR, NET_SSL_TAG, "Unknown cipher");
- return CA_STATUS_FAILED;
+ return SSL_CIPHER_MAX;
}
}
- OIC_LOG_V(DEBUG, NET_SSL_TAG, "Selected cipher: 0x%x", cipher);
+}
+
+CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL context is not initialized." , CA_STATUS_NOT_INITIALIZED);
+
+ SslCipher_t index = GetCipherIndex(cipher);
+ if (SSL_CIPHER_MAX == index)
+ {
+ OIC_LOG(WARNING, NET_SSL_TAG, "Unknown cipher");
+ }
+ else
+ {
+#ifdef __WITH_TLS__
+ CONF_SSL(&g_caSslContext->clientTlsConf, &g_caSslContext->serverTlsConf,
+ mbedtls_ssl_conf_ciphersuites, tlsCipher[index]);
+#endif
+#ifdef __WITH_DTLS__
+ CONF_SSL(&g_caSslContext->clientDtlsConf, &g_caSslContext->serverDtlsConf,
+ mbedtls_ssl_conf_ciphersuites, tlsCipher[index]);
+#endif
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Selected cipher: 0x%x", cipher);
+ }
+ g_caSslContext->cipher = index;
+
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_OK;
}
CAResult_t res = CA_STATUS_OK;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "Param endpoint is NULL" , CA_STATUS_INVALID_PARAM);
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if (NULL == InitiateTlsHandshake(endpoint))
{
OIC_LOG(ERROR, NET_SSL_TAG, "TLS handshake failed");
res = CA_STATUS_FAILED;
}
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return res;
}
VERIFY_NON_NULL_RET(provServerDeviceId, NET_SSL_TAG, "provId is NULL", CA_STATUS_INVALID_PARAM);
VERIFY_NON_NULL_RET(ownerPsk, NET_SSL_TAG, "ownerPSK is NULL", CA_STATUS_INVALID_PARAM);
- // TODO: Added as workaround, need to debug
- ca_mutex_unlock(g_sslContextMutex);
-
- ca_mutex_lock(g_sslContextMutex);
+ oc_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_FAILED;
}
if (NULL == tep)
{
OIC_LOG(ERROR, NET_SSL_TAG, "Session does not exist");
- ca_mutex_unlock(g_sslContextMutex);
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ // keyBlockLen set up according to OIC 1.1 Security Specification Section 7.3.2
+ int macKeyLen = 0;
+ int ivSize = 0;
+ int keySize = 0;
+ int keyBlockLen = 0;
+ if (MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher ||
+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher ||
+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher ||
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher)
+ {
+ // 2 * ( 32 + 0 + 16 ) = 96
+ macKeyLen = SHA256_MAC_KEY_LENGTH;
+ ivSize = CBC_IV_LENGTH;
+ keySize = AES128_KEY_LENGTH;
+ }
+ else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM == g_caSslContext->selectedCipher ||
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caSslContext->selectedCipher)
+ {
+ // 2 * ( 0 + 4 + 16 ) = 40
+ macKeyLen = CCM_MAC_KEY_LENGTH;
+ ivSize = CCM_IV_LENGTH;
+ keySize = AES128_KEY_LENGTH;
+ }
+ else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 == g_caSslContext->selectedCipher)
+ {
+ // 2 * ( 32 + 12 + 16 ) = 120
+ macKeyLen = SHA256_MAC_KEY_LENGTH;
+ ivSize = GCM_IV_LENGTH;
+ keySize = AES128_KEY_LENGTH;
+ }
+ else if (MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 == g_caSslContext->selectedCipher)
+ {
+ // 2 * ( 32 + 0 + 32 ) = 128
+ macKeyLen = SHA256_MAC_KEY_LENGTH;
+ ivSize = CBC_IV_LENGTH;
+ keySize = AES256_KEY_LENGTH;
+ }
+ else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 == g_caSslContext->selectedCipher)
+ {
+ // 2 * ( 48 + 0 + 32 ) = 160
+ macKeyLen = SHA384_MAC_KEY_LENGTH;
+ ivSize = CBC_IV_LENGTH;
+ keySize = AES256_KEY_LENGTH;
+ }
+ else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 == g_caSslContext->selectedCipher)
+ {
+ // 2 * ( 48 + 12 + 32 ) = 184
+ macKeyLen = SHA384_MAC_KEY_LENGTH;
+ ivSize = GCM_IV_LENGTH;
+ keySize = AES256_KEY_LENGTH;
+ }
+ else if (MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 == g_caSslContext->selectedCipher)
+ {
+ // 2 * ( 48 + 12 + 32 ) = 184
+ macKeyLen = SHA256_MAC_KEY_LENGTH;
+ ivSize = GCM_IV_LENGTH;
+ keySize = AES128_KEY_LENGTH;
+ }
+ keyBlockLen = 2 * (macKeyLen + keySize + ivSize);
+
+ uint8_t * keyblock = (uint8_t *)OICMalloc(keyBlockLen);
+ if (NULL == keyblock)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Failed to OICMalloc for keyblock");
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
- uint8_t keyblock[KEY_BLOCK_LEN] = {0};
// "key expansion"
uint8_t lab[] = {0x6b, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e};
int ret = pHash(tep->master, sizeof(tep->master), lab, sizeof(lab),
(tep->random) + RANDOM_LEN, RANDOM_LEN, tep->random, RANDOM_LEN,
- keyblock, KEY_BLOCK_LEN);
+ keyblock, keyBlockLen);
if (-1 == ret)
{
OIC_LOG(ERROR, NET_SSL_TAG, "PSK not generated");
- ca_mutex_unlock(g_sslContextMutex);
+ OICFree(keyblock);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
- ret = pHash(keyblock, sizeof(keyblock), label, labelLen,
+
+ ret = pHash(keyblock, keyBlockLen, label, labelLen,
rsrcServerDeviceId, rsrcServerDeviceIdLen,
provServerDeviceId, provServerDeviceIdLen,
ownerPsk, ownerPskSize);
if (-1 == ret)
{
OIC_LOG(ERROR, NET_SSL_TAG, "PSK not generated");
- ca_mutex_unlock(g_sslContextMutex);
+ OICFree(keyblock);
+ oc_mutex_unlock(g_sslContextMutex);
return CA_STATUS_FAILED;
}
- ca_mutex_unlock(g_sslContextMutex);
+ OICFree(keyblock);
+ oc_mutex_unlock(g_sslContextMutex);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_OK;