Added callback to check peer's certificate Common Name field.
Change-Id: Idb316438a76d70fcc7a91a2e119aadd0c771bde6
Signed-off-by: akk0rd <v.riznyk@samsung.com>
Signed-off-by: Oleksii Beketov <ol.beketov@samsung.com>
ByteArray_t crl; /**< trusted CRLs as binary-encoded DER */
} PkiInfo_t;
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+/**
+ * Callback is used by application layer to check peer's certificate CN field.
+ * If set, this callback will be invoked during handshake after certificate verification.
+ *
+ * @param[out] cn peer's certificate Common Name field.
+ * If common name was not found, cn will be set to NULL.
+ * @param[out] cnLen peer's certificate Common Name field length.
+ * If CN was not found, cnLen will be set to 0.
+ *
+ * @return CA_STATUS_OK or CA_STATUS_FAIL. In case CA_STATUS_FAIL is returned,
+ * handshake will be dropped.
+ */
+typedef CAResult_t (*PeerCNVerifyCallback)(const unsigned char *cn, size_t cnLen);
+
+/**
+ * API to set callback that checks peer's certificate Common Name field
+ * @param[in] cb callback to utilize certificate Common Name field
+ */
+void CAsetPeerCNVerifyCallback(PeerCNVerifyCallback cb);
+#endif
+
/**
* Register callback to get types of TLS suites.
* @param[in] getCredTypesHandler Get types of TLS suites callback.
*/
static CAHandshakeErrorCallback g_sslCallback = NULL;
+/**
+ * @var g_peerCNVerifyCallback
+ *
+ * @brief callback to utilize peer certificate information
+ */
+static PeerCNVerifyCallback g_peerCNVerifyCallback = NULL;
+
/**
* Data structure for holding the data to be received.
*/
g_getPkixInfoCallback = infoCallback;
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
+
void CAsetCredentialTypesCallback(CAgetCredentialTypesHandler credTypesCallback)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
}
+void CAsetPeerCNVerifyCallback(PeerCNVerifyCallback cb)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "IN %s", __func__);
+ if (NULL == cb)
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "UNSET peerCNVerifyCallback");
+ }
+ g_peerCNVerifyCallback = cb;
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "OUT %s", __func__);
+}
+
/**
* Sets SSL result for callback.
*
return result;
}
+static CAResult_t PeerCertExtractCN(const mbedtls_x509_crt *peerCert)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "IN %s", __func__);
+
+ CAResult_t res = CA_STATUS_OK;
+
+ mbedtls_asn1_named_data *subject = (mbedtls_asn1_named_data *)&(peerCert->subject);
+ while (NULL != subject)
+ {
+ if (0 == MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &(subject->oid)))
+ {
+ break;
+ }
+ subject = subject->next;
+ }
+
+ if (NULL != g_peerCNVerifyCallback)
+ {
+ if (NULL != subject)
+ {
+ res = g_peerCNVerifyCallback(subject->val.p, subject->val.len);
+ }
+ else
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "Common Name not found");
+ res = g_peerCNVerifyCallback(NULL, 0);
+ }
+ }
+ else
+ {
+ OIC_LOG(DEBUG, NET_SSL_TAG, "g_peerCNVerifyCallback is not set");
+ }
+
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "OUT %s", __func__);
+ return res;
+}
+
static int GetAdapterIndex(CATransportAdapter_t adapter)
{
switch (adapter)
return CA_STATUS_FAILED;
}
-
SslEndPoint_t * peer = GetSslPeer(&sep->endpoint);
if (NULL == peer)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return CA_STATUS_FAILED;
}
+
+ if (MBEDTLS_SSL_CERTIFICATE_VERIFY == peer->ssl.state)
+ {
+ mbedtls_x509_crt *peerCert = peer->ssl.session_negotiate->peer_cert;
+ if (NULL != peerCert)
+ {
+ ret = PeerCertExtractCN(peerCert);
+ if (CA_STATUS_OK != ret)
+ {
+ oc_mutex_unlock(g_sslContextMutex);
+ OIC_LOG_V(ERROR, NET_SSL_TAG, "ProcessPeerCert failed with %d", ret);
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ return CA_STATUS_FAILED;
+ }
+ }
+ }
+
if (MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC == peer->ssl.state)
{
memcpy(peer->master, peer->ssl.session_negotiate->master, sizeof(peer->master));
#define GetCASecureEndpointData GetCASecureEndpointDataTest
#define SetCASecureEndpointAttribute SetCASecureEndpointAttributeTest
#define GetCASecureEndpointAttributes GetCASecureEndpointAttributesTest
+#define CAsetPeerCNVerifyCallback CAsetPeerCNVerifyCallbackTest
#include "../src/adapter_util/ca_adapter_net_ssl.c"
#include "octypes.h"
#include "pmtypes.h"
+#include "casecurityinterface.h"
#include "ownershiptransfermanager.h"
#ifdef MULTIPLE_OWNER
#include "experimental/securevirtualresourcetypes.h"
OCStackResult OC_CALL OCSelectOwnershipTransferMethod(const OicSecOxm_t *supportedMethods,
size_t numberOfMethods, OicSecOxm_t *selectedMethod, OwnerType_t ownerType);
+/**
+ * Function to set callback to check peer's Common Name field.
+ *
+ * @param[in] cb callback to utilize peer's certificate Common Name information.
+ * If set, callback is invoked during handshake after certificate
+ * verification. It takes peer's certificate CN field and provides
+ * it to application level. Application is to decide whether CN is
+ * valid or not. In case CA_STATUS_FAIL is returned, handshake will
+ * be dropped.
+ */
+void OC_CALL OCSetPeerCNVerifyCallback(PeerCNVerifyCallback cb);
+
#endif // __WITH_DTLS__ || __WITH_TLS__
}
}
+static CAResult_t peerCNVerifyCallback(const unsigned char *cn, size_t cnLen)
+{
+ if (NULL != cn && 0 != cnLen)
+ {
+ OIC_LOG(INFO, TAG, "peer certificate CN: ");
+ OIC_LOG_BUFFER(INFO, TAG, cn, cnLen);
+ return CA_STATUS_OK;
+ }
+ else
+ {
+ return CA_STATUS_FAILED;
+ }
+}
+
static int waitCallbackRet(void)
{
for (int i = 0; !g_doneCB && (CALLBACK_TIMEOUT > i); ++i)
SetDisplayNumCB(NULL, displayNumCB);
SetUserConfirmCB(NULL, confirmNumCB);
+ // set callback for checking peer certificate information
+ OCSetPeerCNVerifyCallback(peerCNVerifyCallback);
+
#ifdef MULTIPLE_OWNER
SetPreconfigPin("12341234", 8);
#endif //MULTIPLE_OWNER
#include <signal.h>
#include "ocstack.h"
#include "ocpayload.h"
+#include "ocprovisioningmanager.h"
#ifdef HAVE_WINDOWS_H
#include <windows.h>
}
}
+static CAResult_t peerCNVerifyCallback(const unsigned char *cn, size_t cnLen)
+{
+ if (NULL != cn && 0 != cnLen)
+ {
+ OIC_LOG(INFO, TAG, "peer certificate CN: ");
+ OIC_LOG_BUFFER(INFO, TAG, cn, cnLen);
+ return CA_STATUS_OK;
+ }
+ else
+ {
+ return CA_STATUS_FAILED;
+ }
+}
+
int main()
{
struct timespec timeout;
OCRegisterPersistentStorageHandler(&ps);
+ // set callback for checking peer certificate information
+ OCSetPeerCNVerifyCallback(peerCNVerifyCallback);
+
if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
{
OIC_LOG(ERROR, TAG, "OCStack init error");
{
SRPRemoveTrustCertChainNotifier();
}
+
+/**
+ * Function to set the callback to utilize peer certificate Common Name field
+ */
+void OC_CALL OCSetPeerCNVerifyCallback(PeerCNVerifyCallback cb)
+{
+ OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
+ CAsetPeerCNVerifyCallback(cb);
+ OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+}
#endif // __WITH_DTLS__ || __WITH_TLS__
OCSaveOwnRoleCert
OCSetOwnerTransferCallbackData
OCSetOxmAllowStatus
+OCSetPeerCNVerifyCallback
OCUnlinkDevices
OCVerifyCSRSignature