From 0f02a3826222509e3598c74c894a9336da23cae5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 10 Sep 2017 08:00:27 +0800 Subject: [PATCH 1/3] openssl wrapper: introduce SSL_get0_param This adds the standard OpenSSL api to get a pointer to the SSL struct's X509_VERIFY_PARAM. We need this for the OpenSSL api to set the peer hostname introduced in the next patch. Part of https://github.com/espressif/esp-idf/pull/980 --- components/openssl/include/openssl/ssl.h | 9 +++++++++ components/openssl/library/ssl_x509.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/components/openssl/include/openssl/ssl.h b/components/openssl/include/openssl/ssl.h index 4af037af6..87a67fc06 100755 --- a/components/openssl/include/openssl/ssl.h +++ b/components/openssl/include/openssl/ssl.h @@ -1523,6 +1523,15 @@ long SSL_get_timeout(const SSL *ssl); */ int SSL_get_verify_mode(const SSL *ssl); +/** + * @brief get SSL verify parameters + * + * @param ssl - SSL point + * + * @return verify parameters + */ +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); + /** * @brief get SSL write only IO handle * diff --git a/components/openssl/library/ssl_x509.c b/components/openssl/library/ssl_x509.c index ef0503c05..bd811e0a9 100644 --- a/components/openssl/library/ssl_x509.c +++ b/components/openssl/library/ssl_x509.c @@ -117,6 +117,15 @@ failed1: return NULL; } +/** + * @brief return SSL X509 verify parameters + */ + +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) +{ + return &ssl->param; +} + /** * @brief set SSL context client CA certification */ From effc6c6d0d15d1d44e2a0d4d87517807aabad5d0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 10 Sep 2017 08:01:38 +0800 Subject: [PATCH 2/3] openssl wrapper: introduce X509_VERIFY_PARAM_set1_host This lets the user code set the mbedtls hostname using the standard OpenSSL X509_VERIFY_PARAM_set1_host() API semantics. The API takes an X509_VERIFY_PARAM pointer. We use the fact that is a composed member of the SSL struct to derive the SSL pointer. The X509_VERIFY_PARAM_set1_host() is unusual in that it can accept a NUL terminated C string as usual, or a nonterminated pointer + length. This implementation converts the latter to the former if given, before using it. This is enough for user code to get the openssl wrapper to make mbedtls confirm the CN on the peer cert belongs to the hostname used to reach it, by doing, eg X509_VERIFY_PARAM_set1_host(SSL_get0_param(myssl), myhostname, 0); Merges https://github.com/espressif/esp-idf/pull/980 --- components/openssl/include/openssl/ssl.h | 14 ++++++++++++ components/openssl/platform/ssl_pm.c | 29 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/components/openssl/include/openssl/ssl.h b/components/openssl/include/openssl/ssl.h index 87a67fc06..ad25f908b 100755 --- a/components/openssl/include/openssl/ssl.h +++ b/components/openssl/include/openssl/ssl.h @@ -1532,6 +1532,20 @@ int SSL_get_verify_mode(const SSL *ssl); */ X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); +/** + * @brief set expected hostname the peer cert CN should have + * + * @param param - verify parameters from SSL_get0_param() + * + * @param name - the expected hostname + * + * @param namelen - the length of the hostname, or 0 if NUL terminated + * + * @return verify parameters + */ +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); + /** * @brief get SSL write only IO handle * diff --git a/components/openssl/platform/ssl_pm.c b/components/openssl/platform/ssl_pm.c index 4fa78ac86..5545f958e 100755 --- a/components/openssl/platform/ssl_pm.c +++ b/components/openssl/platform/ssl_pm.c @@ -669,3 +669,32 @@ long ssl_pm_get_verify_result(const SSL *ssl) return verify_result; } + +/** + * @brief set expected hostname on peer cert CN + */ +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + SSL *ssl = (SSL *)((char *)param - offsetof(SSL, param)); + struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; + char *name_cstr = NULL; + + if (namelen) { + name_cstr = malloc(namelen + 1); + if (!name_cstr) { + return 0; + } + memcpy(name_cstr, name, namelen); + name_cstr[namelen] = '\0'; + name = name_cstr; + } + + mbedtls_ssl_set_hostname(&ssl_pm->ssl, name); + + if (namelen) { + free(name_cstr); + } + + return 1; +} From ae1f1e9b846b87fe0d07500d1c10ff3f29038184 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 10 Sep 2017 08:05:09 +0800 Subject: [PATCH 3/3] openssl wrapper: introduce X509_VERIFY_PARAM_set/clear_hostflags This defines the OpenSSL X509_CHECK_FLAG_...s and the set/clear accessors. Since none of them are supported, the set / clear accessor currently always does nothing and returns error. This call is often part of the generic openssl user code to set up certificate verification. This patch allows it to compile for ESP32 and decide at runtime what to do about unsupported flags. Merges https://github.com/espressif/esp-idf/pull/980 --- components/openssl/include/openssl/ssl.h | 32 ++++++++++++++++++++++++ components/openssl/library/ssl_x509.c | 22 ++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/components/openssl/include/openssl/ssl.h b/components/openssl/include/openssl/ssl.h index ad25f908b..95fd6e9eb 100755 --- a/components/openssl/include/openssl/ssl.h +++ b/components/openssl/include/openssl/ssl.h @@ -26,6 +26,14 @@ { */ +#define SSL_CB_ALERT 0x4000 + +#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT (1 << 0) +#define X509_CHECK_FLAG_NO_WILDCARDS (1 << 1) +#define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS (1 << 2) +#define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS (1 << 3) +#define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS (1 << 4) + /** * @brief create a SSL context * @@ -1546,6 +1554,30 @@ X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, size_t namelen); +/** + * @brief set parameters for X509 host verify action + * + * @param param -verify parameters from SSL_get0_param() + * + * @param flags - bitfield of X509_CHECK_FLAG_... parameters to set + * + * @return 1 for success, 0 for failure + */ +int X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned long flags); + +/** + * @brief clear parameters for X509 host verify action + * + * @param param -verify parameters from SSL_get0_param() + * + * @param flags - bitfield of X509_CHECK_FLAG_... parameters to clear + * + * @return 1 for success, 0 for failure + */ +int X509_VERIFY_PARAM_clear_hostflags(X509_VERIFY_PARAM *param, + unsigned long flags); + /** * @brief get SSL write only IO handle * diff --git a/components/openssl/library/ssl_x509.c b/components/openssl/library/ssl_x509.c index bd811e0a9..50cf2203e 100644 --- a/components/openssl/library/ssl_x509.c +++ b/components/openssl/library/ssl_x509.c @@ -126,6 +126,28 @@ X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) return &ssl->param; } +/** + * @brief set X509 host verification flags + */ + +int X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned long flags) +{ + /* flags not supported yet */ + return 0; +} + +/** + * @brief clear X509 host verification flags + */ + +int X509_VERIFY_PARAM_clear_hostflags(X509_VERIFY_PARAM *param, + unsigned long flags) +{ + /* flags not supported yet */ + return 0; +} + /** * @brief set SSL context client CA certification */