#include "ocrandom.h"
#include "byte_array.h"
#include "octhread.h"
+#include "octypes.h"
#include "timer.h"
*/
#define UUID_LENGTH (128/8)
/**
+ * @def UUID_STR_SIZE
+ * @brief Size of string representation RFC4122 based UUID.
+ * 32 chars for hex data and 4 '-' symbols.
+ */
+#define UUID_STR_SIZE (36)
+
+/**
* @def MASTER_SECRET_LEN
* @brief TLS master secret length
*/
static CAgetPkixInfoHandler g_getPkixInfoCallback = NULL;
/**
+ * Callback to inform in case of client's certificate absence
+ */
+static CertificateVerificationCallback_t g_CertificateVerificationCallback = NULL;
+
+/**
* @var g_setupPkContextCallback
*
* @brief callback to setup PK context handler for H/W based Public Key Infrastructure
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
+void CAsetCertificateVerificationCallback(CertificateVerificationCallback_t certVerifyStatusCallback)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ g_CertificateVerificationCallback = certVerifyStatusCallback;
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+}
+
+void CAunsetCertificateVerificationCallback()
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ g_CertificateVerificationCallback = NULL;
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+}
+
static int GetAdapterIndex(CATransportAdapter_t adapter)
{
switch (adapter)
else if ((size_t)sentLen != dataLen)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG,
- "Packet was partially sent - total/sent/remained bytes : %zd/%zu/%lu",
+ "Packet was partially sent - total/sent/remained bytes : %zd/%zu/%zu",
sentLen, dataLen, (dataLen - sentLen));
}
}
else
{
unsigned char * lastCert = (unsigned char *)OICMalloc((len + 1) * sizeof(unsigned char));
+ if (lastCert == NULL)
+ {
+ goto exit;
+ }
memcpy(lastCert, buf + pos, len);
lastCert[len] = 0x00;
ret = mbedtls_x509_crt_parse(crt, lastCert, len + 1);
}
#endif
+CAResult_t SetCASecureEndpointUuid(const CAEndpoint_t *peer, const char *uuid)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+ VERIFY_NON_NULL(peer, NET_SSL_TAG, "peer");
+ VERIFY_NON_NULL(peer, NET_SSL_TAG, "uuid");
+
+ oc_mutex_lock(g_sslContextMutex);
+ SslEndPoint_t *sslPeer = GetSslPeer(peer);
+ if (NULL == sslPeer)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Peer not found");
+ oc_mutex_unlock(g_sslContextMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ OCRandomUuidResult ret = OCConvertStringToUuid(uuid, sslPeer->sep.identity.id);
+ oc_mutex_unlock(g_sslContextMutex);
+
+ if (RAND_UUID_OK != ret)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Failed to convert uuid");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+
+ return CA_STATUS_OK;
+}
+
/**
* Deletes cached message.
*
&& (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);
+ DeleteSslEndPoint(tep);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return;
}
return CA_STATUS_OK;
}
+#ifdef __TIZEN__
+CAResult_t CAcloseSslConnectionFreeEndpoint(CAEndpoint_t *endpoint)
+{
+ 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);
+
+ CAResult_t ret = CAcloseSslConnection(endpoint);
+ OICFree(endpoint);
+
+ OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
+ return ret;
+}
+#endif //__TIZEN__
+
CAResult_t CAcloseSslConnectionUsingUuid(const uint8_t *identity, size_t idLength)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
memset(g_cipherSuitesList, 0, sizeof(g_cipherSuitesList));
+ if (SSL_CIPHER_MAX < g_caSslContext->cipher)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Maximum ciphersuite index exceeded");
+ }
+
// Add the preferred ciphersuite first
if (SSL_CIPHER_MAX != g_caSslContext->cipher)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
+/**
+ * Check RFC4122 based UUID
+ *
+ * @param uuidString string representation of UUID
+ * @return true for success, otherwise false
+ */
+static bool CheckUuidFormat(const char uuidString[UUID_STR_SIZE])
+{
+ // Indexes of '-' symbols in string representation of UUID
+ static const int dash_idxs[4] = {8,13,18,23};
+
+ VERIFY_NON_NULL_RET(uuidString, NET_SSL_TAG, "uuidString is NULL" , false);
+
+ // Check for '-' symbols
+ for (int i = 0; i < 4; i++)
+ {
+ if (uuidString[dash_idxs[i]] != '-')
+ {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < UUID_STR_SIZE; i++)
+ {
+ // Skip '-' symbols
+ if (i == dash_idxs[0] || i == dash_idxs[1] || i == dash_idxs[2] || i == dash_idxs[3])
+ {
+ continue;
+ }
+
+ if ((uuidString[i] >= 'a' && uuidString[i] <= 'f')
+ || (uuidString[i] >= 'A' && uuidString[i] <= 'F')
+ || (uuidString[i] >= '0' && uuidString[i] <= '9') )
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * FindUuid function finds the first entry of RFC4122 based UUID
+ *
+ * @param data pointer to unformatted data
+ * @param size data size
+ *
+ * @return pointer to string representation of the found UUID if success, otherwise NULL
+ */
+static const char* FindUuid(const char* data, size_t size)
+{
+ const char* result = NULL;
+
+ VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "data is NULL" , NULL);
+ if (size < UUID_STR_SIZE)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Buffer size is too small");
+ return NULL;
+ }
+
+ const char* currentPtr = data;
+ int currentSize = size;
+ while (!result
+ && (currentPtr = (const char*)memchr((const void*)++currentPtr, '-', currentSize - 1))
+ && ((currentSize = (size - (currentPtr - data))) >= (UUID_STR_SIZE - 8)))
+ {
+ if (currentPtr - data >= 8 && CheckUuidFormat(currentPtr - 8))
+ {
+ result = currentPtr - 8;
+ }
+ }
+
+ return result;
+}
+
/* Read data from TLS connection
*/
CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t dataLen)
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);
+ if (0 == dataLen)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "dataLen is zero");
+ return CA_STATUS_FAILED;
+ }
+
oc_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
return CA_STATUS_FAILED;
}
-
SslEndPoint_t * peer = GetSslPeer(&sep->endpoint);
if (NULL == peer)
{
sizeof(sep->endpoint.addr));
ret = mbedtls_ssl_handshake_step(&peer->ssl);
}
- if (MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint)
+ uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
+ if (0 != flags &&
+ ((MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint) ||
+ (MBEDTLS_SSL_IS_SERVER == peer->ssl.conf->endpoint && MBEDTLS_X509_BADCERT_MISSING != 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));
- }
+ 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)
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);
+ if (g_CertificateVerificationCallback)
+ {
+ uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
+ if (!flags)
+ {
+ g_CertificateVerificationCallback(CA_CERTIFICATE_VERIFY_SUCCESS_MUTUAL);
+ }
+ else if (MBEDTLS_X509_BADCERT_MISSING == flags)
+ {
+ g_CertificateVerificationCallback(CA_CERTIFICATE_VERIFY_NO_CERT);
+ }
+ else
+ {
+ g_CertificateVerificationCallback(CA_CERTIFICATE_VERIFY_FAILED);
+ }
+ }
//SSL_CHECK_FAIL(peer, ret, "Failed to retrieve cert", 1,
// CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_NO_CERT);
if (0 == ret)
{
- uuidPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
- UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
-
- if (NULL != uuidPos)
+ const char* uuidptr = FindUuid((const char*)peerCert->subject_raw.p, peerCert->subject_raw.len);
+ if (uuidptr)
{
- memcpy(uuid, (char*) uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
+ char uuid[UUID_STR_SIZE + 1] = {0};
+ strncpy(uuid, uuidptr, UUID_STR_SIZE);
+ uuid[UUID_STR_SIZE] = '\0';
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,
{
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");
- }
}
}