X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fadapter_util%2Fca_adapter_net_ssl.c;h=7b8f60e16313bbcdff23cf55578134e3205fba78;hb=7f00f942c39b7bc27c7eeecf213a239c3fe4173c;hp=c555b586099df564c807ce66ee90937808beb0d2;hpb=86d9faf6e92ddb3f882bdf6ee0764dabded1e5aa;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c b/resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c index c555b58..7b8f60e 100644 --- a/resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c +++ b/resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c @@ -18,16 +18,24 @@ * ******************************************************************/ +#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif // _GNU_SOURCE #include +#include #include #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" @@ -38,10 +46,12 @@ #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" #if !defined(NDEBUG) || defined(TB_LOG) #include "mbedtls/debug.h" @@ -97,8 +107,12 @@ * @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 @@ -120,18 +134,45 @@ */ #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 KEY_BLOCK_LEN (96) - -/**@def SSL_CLOSE_NOTIFY(peer, ret) - * - * Notifies of existing \a peer about closing TLS connection. - * - * @param[in] peer remote peer - * @param[in] ret used internaly +#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 @@ -139,6 +180,13 @@ */ #define RETRANSMISSION_TIME 1 +/**@def SSL_CLOSE_NOTIFY(peer, ret) + * + * Notifies of existing \a peer about closing TLS connection. + * + * @param[in] peer remote peer + * @param[in] ret used internaly + */ #define SSL_CLOSE_NOTIFY(peer, ret) \ do \ { \ @@ -166,40 +214,62 @@ if (g_sslCallback) * @param[in] ret error code * @param[in] str debug string * @param[in] mutex ca mutex - * @param[in] if code does not equal to -1 returns 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__); \ - if (-1 != 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 * @@ -212,16 +282,25 @@ int ret = (f)(__VA_ARGS__); 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 { @@ -229,15 +308,35 @@ 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] = { @@ -310,7 +409,7 @@ static void DebugSsl(void *ctx, int level, const char *file, int line, const cha } #endif -#if defined(_WIN32) +#if defined(_WIN32) || defined (__TIZENRT__) /* * Finds the first occurrence of the byte string s in byte string l. */ @@ -380,16 +479,16 @@ typedef struct SslContext mbedtls_ssl_config clientDtlsConf; mbedtls_ssl_config serverDtlsConf; - 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; /** @@ -398,6 +497,10 @@ typedef struct SslContext */ 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) @@ -416,10 +519,17 @@ static CAgetCredentialTypesHandler g_getCredentialTypesCallback = NULL; 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 @@ -428,6 +538,28 @@ static ca_mutex g_sslContextMutex = NULL; 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 @@ -449,7 +581,6 @@ typedef struct SslEndPoint uint8_t master[MASTER_SECRET_LEN]; uint8_t random[2*RANDOM_LEN]; #ifdef __WITH_DTLS__ - mbedtls_ssl_cookie_ctx cookieCtx; mbedtls_timing_delay_context timer; #endif // __WITH_DTLS__ } SslEndPoint_t; @@ -468,6 +599,14 @@ void CAsetPkixInfoCallback(CAgetPkixInfoHandler infoCallback) 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__); @@ -483,6 +622,8 @@ static int GetAdapterIndex(CATransportAdapter_t adapter) 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; @@ -499,30 +640,37 @@ static int GetAdapterIndex(CATransportAdapter_t adapter) */ static int SendCallBack(void * tep, const unsigned char * data, size_t dataLen) { - OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__); + 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; sentLen = sendCallback(&(((SslEndPoint_t * )tep)->sep.endpoint), (const void *) data, dataLen); - if (sentLen != 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 : %d/%d/%d", - sentLen, dataLen, (dataLen - sentLen)); + "Packet was partially sent - total/sent/remained bytes : %zd/%zu/%lu", + sentLen, dataLen, (dataLen - sentLen)); } } else { OIC_LOG(ERROR, NET_SSL_TAG, "Unsupported adapter"); + return -1; } - OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__); + OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__); return sentLen; } /** @@ -551,27 +699,138 @@ static int RecvCallBack(void * tep, unsigned char * data, size_t dataLen) 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 @@ -583,6 +842,13 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buf 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) @@ -591,11 +857,21 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buf 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); @@ -605,47 +881,124 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buf 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); @@ -657,19 +1010,88 @@ static int InitPKIX(CATransportAdapter_t adapter) 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"); @@ -690,28 +1112,32 @@ static int InitPKIX(CATransportAdapter_t adapter) } 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; } @@ -755,6 +1181,7 @@ static int GetPskCredentialsCallback(void * notUsed, mbedtls_ssl_context * ssl, OIC_LOG_V(WARNING, NET_SSL_TAG, "Out %s", __func__); return -1; } + /** * Gets session corresponding for endpoint. * @@ -768,6 +1195,7 @@ static SslEndPoint_t *GetSslPeer(const CAEndpoint_t *peer) 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); @@ -778,21 +1206,98 @@ static SslEndPoint_t *GetSslPeer(const CAEndpoint_t *peer) { 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_ +bool CAIsExistSslPeer(const CAEndpoint_t *peer) +{ + 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. * @@ -805,13 +1310,13 @@ 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; } @@ -819,13 +1324,13 @@ const CASecureEndpoint_t *GetCASecureEndpointData(const CAEndpoint_t* peer) 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 @@ -881,9 +1386,6 @@ static void DeleteSslEndPoint(SslEndPoint_t * tep) 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__); @@ -893,10 +1395,12 @@ static void DeleteSslEndPoint(SslEndPoint_t * tep) * * @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); @@ -905,19 +1409,28 @@ static void RemovePeerFromList(CAEndpoint_t * endpoint) 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++) { @@ -926,6 +1439,15 @@ static void DeletePeerList() { 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); @@ -933,23 +1455,59 @@ static void DeletePeerList() 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 @@ -959,33 +1517,42 @@ CAResult_t CAcloseSslConnection(const CAEndpoint_t *endpoint) 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; @@ -995,9 +1562,11 @@ void CAcloseSslConnectionAll() } 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; @@ -1013,9 +1582,10 @@ void CAcloseSslConnectionAll() 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) @@ -1031,7 +1601,7 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl { 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; } @@ -1042,20 +1612,11 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl 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; @@ -1071,6 +1632,9 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl 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; } @@ -1083,17 +1647,20 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl */ 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__); @@ -1106,22 +1673,23 @@ static void SetupCipher(mbedtls_ssl_config * config, CATransportAdapter_t adapte { 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) @@ -1131,19 +1699,47 @@ static void SetupCipher(mbedtls_ssl_config * config, CATransportAdapter_t adapte } 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); @@ -1162,11 +1758,15 @@ static SslEndPoint_t * InitiateTlsHandshake(const CAEndpoint_t *endpoint) 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) @@ -1178,7 +1778,6 @@ static SslEndPoint_t * InitiateTlsHandshake(const CAEndpoint_t *endpoint) //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) { @@ -1194,9 +1793,15 @@ static SslEndPoint_t * InitiateTlsHandshake(const CAEndpoint_t *endpoint) { 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__ @@ -1208,6 +1813,7 @@ static void StopRetransmit() if (g_caSslContext) { unregisterTimer(g_caSslContext->timerId); + g_caSslContext->timerId= -1; } } #endif @@ -1219,14 +1825,16 @@ void CAdeinitSslAdapter() 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); @@ -1234,6 +1842,7 @@ void CAdeinitSslAdapter() #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); @@ -1244,9 +1853,16 @@ void CAdeinitSslAdapter() 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__); @@ -1256,6 +1872,7 @@ static int InitConfig(mbedtls_ssl_config * conf, int transport, int mode) { 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) { @@ -1269,6 +1886,16 @@ static int InitConfig(mbedtls_ssl_config * conf, int transport, int mode) 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); + +#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); @@ -1286,39 +1913,48 @@ 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; } - ca_mutex_lock(g_sslContextMutex); 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 - || MBEDTLS_SSL_TRANSPORT_STREAM == tep->ssl.conf->transport + || (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) { - SSL_CHECK_FAIL(tep, ret, "Retransmission", NULL, -1, + //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); - ca_mutex_unlock(g_sslContextMutex); + oc_mutex_unlock(g_sslContextMutex); + return 0; } #endif @@ -1329,7 +1965,7 @@ 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 @@ -1339,14 +1975,14 @@ CAResult_t CAinitSslAdapter() } // 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; } @@ -1359,8 +1995,8 @@ CAResult_t CAinitSslAdapter() 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; } @@ -1385,7 +2021,7 @@ CAResult_t CAinitSslAdapter() 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; } @@ -1393,7 +2029,7 @@ CAResult_t CAinitSslAdapter() { 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; } @@ -1406,7 +2042,7 @@ CAResult_t CAinitSslAdapter() &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; } @@ -1417,7 +2053,7 @@ CAResult_t CAinitSslAdapter() 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; @@ -1427,18 +2063,29 @@ CAResult_t CAinitSslAdapter() 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; @@ -1448,7 +2095,7 @@ CAResult_t CAinitSslAdapter() 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; @@ -1456,7 +2103,7 @@ CAResult_t CAinitSslAdapter() #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); @@ -1468,7 +2115,18 @@ CAResult_t CAinitSslAdapter() g_caSslContext->timerId = -1; #endif - ca_mutex_unlock(g_sslContextMutex); + // 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 @@ -1516,7 +2174,7 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint, { 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); @@ -1530,11 +2188,11 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint, 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; } @@ -1546,21 +2204,37 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint, 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)"); + + unsigned char *dataBuf = (unsigned char *)data; + size_t written = 0; - if(ret < 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 { @@ -1568,14 +2242,14 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint, 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; } /** @@ -1597,16 +2271,27 @@ static void SendCacheMessages(SslEndPoint_t * tep) 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); @@ -1634,70 +2319,21 @@ void CAsetSslHandshakeCallback(CAErrorCallback tlsHandshakeCallback) 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; } @@ -1705,13 +2341,14 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d 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 @@ -1722,7 +2359,7 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d { 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; } } @@ -1748,12 +2385,15 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d 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) @@ -1774,97 +2414,148 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d 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; } @@ -1875,131 +2566,130 @@ void CAsetSslAdapterCallbacks(CAPacketReceivedCallback recvCallback, 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; } @@ -2009,13 +2699,13 @@ CAResult_t CAinitiateSslHandshake(const CAEndpoint_t *endpoint) 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; } @@ -2131,14 +2821,11 @@ CAResult_t CAsslGenerateOwnerPsk(const CAEndpoint_t *endpoint, 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; } @@ -2146,34 +2833,105 @@ CAResult_t CAsslGenerateOwnerPsk(const CAEndpoint_t *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; + } + + // 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;