From 0bdc49221b325feb3a09988737559361fe916be2 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 27 Apr 2014 22:27:53 +0200 Subject: PolarSSL wrappers for the SSL context. --- src/PolarSSL++/SslContext.cpp | 181 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/PolarSSL++/SslContext.cpp (limited to 'src/PolarSSL++/SslContext.cpp') diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp new file mode 100644 index 000000000..e7fa11c75 --- /dev/null +++ b/src/PolarSSL++/SslContext.cpp @@ -0,0 +1,181 @@ + +// SslContext.cpp + +// Implements the cSslContext class that holds everything a single SSL context needs to function + +#include "Globals.h" +#include "SslContext.h" +#include "EntropyContext.h" +#include "CtrDrbgContext.h" + + + + + +cSslContext::cSslContext(void) : + m_IsValid(false), + m_HasHandshaken(false) +{ +} + + + + + +cSslContext::~cSslContext() +{ + if (m_IsValid) + { + ssl_free(&m_Ssl); + } +} + + + + + +int cSslContext::Initialize(bool a_IsClient, const SharedPtr & a_CtrDrbg) +{ + // Check double-initialization: + if (m_IsValid) + { + LOGWARNING("SSL: Double initialization is not supported."); + return POLARSSL_ERR_SSL_MALLOC_FAILED; // There is no return value well-suited for this, reuse this one. + } + + // Set the CtrDrbg context, create a new one if needed: + m_CtrDrbg = a_CtrDrbg; + if (m_CtrDrbg.get() == NULL) + { + m_CtrDrbg.reset(new cCtrDrbgContext); + m_CtrDrbg->Initialize("MCServer", 8); + } + + // Initialize PolarSSL's structures: + memset(&m_Ssl, 0, sizeof(m_Ssl)); + int res = ssl_init(&m_Ssl); + if (res != 0) + { + return res; + } + ssl_set_endpoint(&m_Ssl, a_IsClient ? SSL_IS_CLIENT : SSL_IS_SERVER); + ssl_set_authmode(&m_Ssl, SSL_VERIFY_OPTIONAL); + ssl_set_rng(&m_Ssl, ctr_drbg_random, &m_CtrDrbg->m_CtrDrbg); + ssl_set_bio(&m_Ssl, ReceiveEncrypted, this, SendEncrypted, this); + + #ifdef _DEBUG + ssl_set_dbg(&m_Ssl, &SSLDebugMessage, this); + #endif + + m_IsValid = true; + return 0; +} + + + + + +void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName) +{ + // Store the data in our internal buffers, to avoid losing the pointers later on + // PolarSSL will need these after this call returns, and the caller may move / delete the data before that: + m_ExpectedPeerName = a_ExpectedPeerName; + m_CACerts = a_CACert; + + // Set the trusted CA root cert store: + ssl_set_authmode(&m_Ssl, SSL_VERIFY_REQUIRED); + ssl_set_ca_chain(&m_Ssl, m_CACerts->GetInternal(), NULL, m_ExpectedPeerName.empty() ? NULL : m_ExpectedPeerName.c_str()); +} + + + + + +int cSslContext::WritePlain(const void * a_Data, size_t a_NumBytes) +{ + ASSERT(m_IsValid); // Need to call Initialize() first + if (!m_HasHandshaken) + { + int res = Handshake(); + if (res != 0) + { + return res; + } + } + + return ssl_write(&m_Ssl, (const unsigned char *)a_Data, a_NumBytes); +} + + + + + +int cSslContext::ReadPlain(void * a_Data, size_t a_MaxBytes) +{ + ASSERT(m_IsValid); // Need to call Initialize() first + if (!m_HasHandshaken) + { + int res = Handshake(); + if (res != 0) + { + return res; + } + } + + return ssl_read(&m_Ssl, (unsigned char *)a_Data, a_MaxBytes); +} + + + + + +int cSslContext::Handshake(void) +{ + ASSERT(m_IsValid); // Need to call Initialize() first + ASSERT(!m_HasHandshaken); // Must not call twice + + int res = ssl_handshake(&m_Ssl); + if (res == 0) + { + m_HasHandshaken = true; + } + return res; +} + + + + + +int cSslContext::NotifyClose(void) +{ + return ssl_close_notify(&m_Ssl); +} + + + + + +#ifdef _DEBUG + void cSslContext::SSLDebugMessage(void * a_UserParam, int a_Level, const char * a_Text) + { + if (a_Level > 3) + { + // Don't want the trace messages + return; + } + + // Remove the terminating LF: + size_t len = strlen(a_Text) - 1; + while ((len > 0) && (a_Text[len] <= 32)) + { + len--; + } + AString Text(a_Text, len + 1); + + LOGD("SSL (%d): %s", a_Level, Text.c_str()); + } +#endif // _DEBUG + + + + -- cgit v1.2.3 From 16b3eae8623916fa7bc2cd9cad292bbad8d6a116 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 28 Apr 2014 21:16:32 +0200 Subject: Added a debug cert printing function. --- src/PolarSSL++/SslContext.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'src/PolarSSL++/SslContext.cpp') diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp index e7fa11c75..1994cf844 100644 --- a/src/PolarSSL++/SslContext.cpp +++ b/src/PolarSSL++/SslContext.cpp @@ -64,7 +64,12 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr & ssl_set_bio(&m_Ssl, ReceiveEncrypted, this, SendEncrypted, this); #ifdef _DEBUG + /* + // These functions allow us to debug SSL and certificate problems, but produce way too much output, + // so they're disabled until someone needs them ssl_set_dbg(&m_Ssl, &SSLDebugMessage, this); + ssl_set_verify(&m_Ssl, &SSLVerifyCert, this); + */ #endif m_IsValid = true; @@ -174,6 +179,63 @@ int cSslContext::NotifyClose(void) LOGD("SSL (%d): %s", a_Level, Text.c_str()); } + + + + + + int cSslContext::SSLVerifyCert(void * a_This, x509_crt * a_Crt, int a_Depth, int * a_Flags) + { + char buf[1024]; + UNUSED(a_This); + + LOG("Verify requested for (Depth %d):", a_Depth); + x509_crt_info(buf, sizeof(buf) - 1, "", a_Crt); + LOG("%s", buf); + + int Flags = *a_Flags; + if ((Flags & BADCERT_EXPIRED) != 0) + { + LOG(" ! server certificate has expired"); + } + + if ((Flags & BADCERT_REVOKED) != 0) + { + LOG(" ! server certificate has been revoked"); + } + + if ((Flags & BADCERT_CN_MISMATCH) != 0) + { + LOG(" ! CN mismatch"); + } + + if ((Flags & BADCERT_NOT_TRUSTED) != 0) + { + LOG(" ! self-signed or not signed by a trusted CA"); + } + + if ((Flags & BADCRL_NOT_TRUSTED) != 0) + { + LOG(" ! CRL not trusted"); + } + + if ((Flags & BADCRL_EXPIRED) != 0) + { + LOG(" ! CRL expired"); + } + + if ((Flags & BADCERT_OTHER) != 0) + { + LOG(" ! other (unknown) flag"); + } + + if (Flags == 0) + { + LOG(" This certificate has no flags"); + } + + return 0; + } #endif // _DEBUG -- cgit v1.2.3 From 47feb91e57f83c81722188ec3025c3109758dd33 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 1 May 2014 00:28:27 +0200 Subject: cSslContext supports setting own cert / privkey. --- src/PolarSSL++/SslContext.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'src/PolarSSL++/SslContext.cpp') diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp index 1994cf844..3d2b8cef7 100644 --- a/src/PolarSSL++/SslContext.cpp +++ b/src/PolarSSL++/SslContext.cpp @@ -40,7 +40,7 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr & if (m_IsValid) { LOGWARNING("SSL: Double initialization is not supported."); - return POLARSSL_ERR_SSL_MALLOC_FAILED; // There is no return value well-suited for this, reuse this one. + return POLARSSL_ERR_SSL_BAD_INPUT_DATA; // There is no return value well-suited for this, reuse this one. } // Set the CtrDrbg context, create a new one if needed: @@ -80,8 +80,56 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr & +void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cRsaPrivateKeyPtr & a_OwnCertPrivKey) +{ + ASSERT(m_IsValid); // Call Initialize() first + + // Check that both the cert and the key is valid: + if ((a_OwnCert.get() == NULL) || (a_OwnCertPrivKey.get() == NULL)) + { + LOGWARNING("SSL: Own certificate is not valid, skipping the set."); + return; + } + + // Make sure we have the cert stored for later, PolarSSL only uses the cert later on + m_OwnCert = a_OwnCert; + m_OwnCertPrivKey = a_OwnCertPrivKey; + + // Set into the context: + ssl_set_own_cert_rsa(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey->GetInternal()); +} + + + + + +void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cPublicKeyPtr & a_OwnCertPrivKey) +{ + ASSERT(m_IsValid); // Call Initialize() first + + // Check that both the cert and the key is valid: + if ((a_OwnCert.get() == NULL) || (a_OwnCertPrivKey.get() == NULL)) + { + LOGWARNING("SSL: Own certificate is not valid, skipping the set."); + return; + } + + // Make sure we have the cert stored for later, PolarSSL only uses the cert later on + m_OwnCert = a_OwnCert; + m_OwnCertPrivKey2 = a_OwnCertPrivKey; + + // Set into the context: + ssl_set_own_cert(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey2->GetInternal()); +} + + + + + void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName) { + ASSERT(m_IsValid); // Call Initialize() first + // Store the data in our internal buffers, to avoid losing the pointers later on // PolarSSL will need these after this call returns, and the caller may move / delete the data before that: m_ExpectedPeerName = a_ExpectedPeerName; -- cgit v1.2.3 From e1b6a169457b267c3e11bbdb9e58e9ab7b3f0136 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 1 May 2014 11:33:29 +0200 Subject: Added a (disabled) test of low-security ciphersuites. Enabling this allows the connection to be sniffed and decoded using Wireshark, when given the SSL private key. --- src/PolarSSL++/SslContext.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/PolarSSL++/SslContext.cpp') diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp index 3d2b8cef7..df0219610 100644 --- a/src/PolarSSL++/SslContext.cpp +++ b/src/PolarSSL++/SslContext.cpp @@ -70,6 +70,18 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr & ssl_set_dbg(&m_Ssl, &SSLDebugMessage, this); ssl_set_verify(&m_Ssl, &SSLVerifyCert, this); */ + + /* + // Set ciphersuite to the easiest one to decode, so that the connection can be wireshark-decoded: + static const int CipherSuites[] = + { + TLS_RSA_WITH_RC4_128_MD5, + TLS_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA, + 0, // Must be 0-terminated! + }; + ssl_set_ciphersuites(&m_Ssl, CipherSuites); + */ #endif m_IsValid = true; -- cgit v1.2.3 From 1587b21edded56dbfb88150500336c2853b460c6 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 1 May 2014 15:21:41 +0200 Subject: Renamed cPublicKey to cCryptoKey. The class can hold both the private key and the public key, bad naming on PolarSSL's part. Also somewhat fixed the cert and key loading in cHTTPServer. --- src/PolarSSL++/SslContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/PolarSSL++/SslContext.cpp') diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp index df0219610..bc397b655 100644 --- a/src/PolarSSL++/SslContext.cpp +++ b/src/PolarSSL++/SslContext.cpp @@ -115,7 +115,7 @@ void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cRsaPrivateKe -void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cPublicKeyPtr & a_OwnCertPrivKey) +void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cCryptoKeyPtr & a_OwnCertPrivKey) { ASSERT(m_IsValid); // Call Initialize() first -- cgit v1.2.3 From 683b839e2b3e634dd1a0a5b85327efe4ffa968fd Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 10 May 2014 09:21:29 +0200 Subject: Client cert is not requested. --- src/PolarSSL++/SslContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/PolarSSL++/SslContext.cpp') diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp index bc397b655..c3074f197 100644 --- a/src/PolarSSL++/SslContext.cpp +++ b/src/PolarSSL++/SslContext.cpp @@ -59,7 +59,7 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr & return res; } ssl_set_endpoint(&m_Ssl, a_IsClient ? SSL_IS_CLIENT : SSL_IS_SERVER); - ssl_set_authmode(&m_Ssl, SSL_VERIFY_OPTIONAL); + ssl_set_authmode(&m_Ssl, a_IsClient ? SSL_VERIFY_OPTIONAL : SSL_VERIFY_NONE); // Clients ask for server's cert but don't verify strictly; servers don't ask clients for certs by default ssl_set_rng(&m_Ssl, ctr_drbg_random, &m_CtrDrbg->m_CtrDrbg); ssl_set_bio(&m_Ssl, ReceiveEncrypted, this, SendEncrypted, this); -- cgit v1.2.3