[PATCH ustream-ssl 08/12] ustream-openssl: wolfSSL: fix certificate validation
Petr Štetiar
ynezz at true.cz
Thu Dec 10 10:41:30 EST 2020
Currently wolfSSL doesn't validate any certificates, quoting from
README:
wolfSSL takes a different approach to certificate verification than
OpenSSL does. The default policy for the client is to verify the server,
this means that if you don't load CAs to verify the server you'll get a
connect error, no signer error to confirm failure (-188).
If you want to mimic OpenSSL behavior of having SSL_connect succeed even if
verifying the server fails and reducing security you can do this by calling:
wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
before calling wolfSSL_new();. Though it's not recommended.
wolfSSL simply behaves differently then OpenSSL so once you set
SSL_VERIFY_NONE wolfSSL doesn't care about the certificates anymore so
every call to SSL_get_verify_result() is going to succeed (returns
X509_V_OK) even for invalid certificates and current OpenSSL based post
connection verification logic thus doesn't work.
So in order to get the validation working we need to use SSL_VERIFY_PEER
for wolfSSL by default and allow disabling it explicitly by new
`context_set_require_validation()` call. In order to keep the same error
handling/messages via `notify_verify_error()` callback we as well need
to handle certificate errors manually.
Fixes: FS#3465
Signed-off-by: Petr Štetiar <ynezz at true.cz>
---
ustream-internal.h | 1 +
ustream-openssl.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
ustream-ssl.c | 1 +
ustream-ssl.h | 19 +++++++-----
4 files changed, 86 insertions(+), 8 deletions(-)
diff --git a/ustream-internal.h b/ustream-internal.h
index 147141ab5f05..e80abf827515 100644
--- a/ustream-internal.h
+++ b/ustream-internal.h
@@ -39,6 +39,7 @@ int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file);
int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file);
int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers);
+int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, bool require);
void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx);
enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us);
int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len);
diff --git a/ustream-openssl.c b/ustream-openssl.c
index ad77e721534c..9b4ac6c80894 100644
--- a/ustream-openssl.c
+++ b/ustream-openssl.c
@@ -130,7 +130,15 @@ __ustream_ssl_context_new(bool server)
if (!c)
return NULL;
+#if defined(HAVE_WOLFSSL)
+ if (server)
+ SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
+ else
+ SSL_CTX_set_verify(c, SSL_VERIFY_PEER, NULL);
+#else
SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
+#endif
+
SSL_CTX_set_options(c, SSL_OP_NO_COMPRESSION | SSL_OP_SINGLE_ECDH_USE |
SSL_OP_CIPHER_SERVER_PREFERENCE);
#if defined(SSL_CTX_set_ecdh_auto) && OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -203,6 +211,18 @@ __hidden int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *
return 0;
}
+__hidden int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, bool require)
+{
+ int mode = SSL_VERIFY_PEER;
+
+ if (!require)
+ mode = SSL_VERIFY_NONE;
+
+ SSL_CTX_set_verify((void *) ctx, mode, NULL);
+
+ return 0;
+}
+
__hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx)
{
SSL_CTX_free((void *) ctx);
@@ -270,6 +290,54 @@ static void ustream_ssl_verify_cert(struct ustream_ssl *us)
X509_free(cert);
}
+#ifdef WOLFSSL_SSL_H
+static bool handle_wolfssl_asn_error(struct ustream_ssl *us, int r)
+{
+ switch (r) {
+ case ASN_PARSE_E:
+ case ASN_VERSION_E:
+ case ASN_GETINT_E:
+ case ASN_RSA_KEY_E:
+ case ASN_OBJECT_ID_E:
+ case ASN_TAG_NULL_E:
+ case ASN_EXPECT_0_E:
+ case ASN_BITSTR_E:
+ case ASN_UNKNOWN_OID_E:
+ case ASN_DATE_SZ_E:
+ case ASN_BEFORE_DATE_E:
+ case ASN_AFTER_DATE_E:
+ case ASN_SIG_OID_E:
+ case ASN_TIME_E:
+ case ASN_INPUT_E:
+ case ASN_SIG_CONFIRM_E:
+ case ASN_SIG_HASH_E:
+ case ASN_SIG_KEY_E:
+ case ASN_DH_KEY_E:
+ case ASN_NTRU_KEY_E:
+ case ASN_CRIT_EXT_E:
+ case ASN_ALT_NAME_E:
+ case ASN_NO_PEM_HEADER:
+ case ASN_ECC_KEY_E:
+ case ASN_NO_SIGNER_E:
+ case ASN_CRL_CONFIRM_E:
+ case ASN_CRL_NO_SIGNER_E:
+ case ASN_OCSP_CONFIRM_E:
+ case ASN_NAME_INVALID_E:
+ case ASN_NO_SKID:
+ case ASN_NO_AKID:
+ case ASN_NO_KEYUSAGE:
+ case ASN_COUNTRY_SIZE_E:
+ case ASN_PATHLEN_SIZE_E:
+ case ASN_PATHLEN_INV_E:
+ case ASN_SELF_SIGNED_E:
+ if (us->notify_verify_error)
+ us->notify_verify_error(us, r, wc_GetErrorString(r));
+ return true;
+ }
+
+ return false;
+}
+#endif
__hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us)
{
@@ -292,6 +360,11 @@ __hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us)
if (r == SSL_ERROR_WANT_READ || r == SSL_ERROR_WANT_WRITE)
return U_SSL_PENDING;
+#ifdef WOLFSSL_SSL_H
+ if (handle_wolfssl_asn_error(us, r))
+ return U_SSL_OK;
+#endif
+
ustream_ssl_error(us, r);
return U_SSL_ERROR;
}
diff --git a/ustream-ssl.c b/ustream-ssl.c
index dbc3bee00e27..46ac5523d999 100644
--- a/ustream-ssl.c
+++ b/ustream-ssl.c
@@ -232,6 +232,7 @@ const struct ustream_ssl_ops ustream_ssl_ops = {
.context_set_key_file = __ustream_ssl_set_key_file,
.context_add_ca_crt_file = __ustream_ssl_add_ca_crt_file,
.context_set_ciphers = __ustream_ssl_set_ciphers,
+ .context_set_require_validation = __ustream_ssl_set_require_validation,
.context_free = __ustream_ssl_context_free,
.init = _ustream_ssl_init,
.set_peer_cn = _ustream_ssl_set_peer_cn,
diff --git a/ustream-ssl.h b/ustream-ssl.h
index db89297604a9..87c0ae6da595 100644
--- a/ustream-ssl.h
+++ b/ustream-ssl.h
@@ -42,6 +42,7 @@ struct ustream_ssl {
bool valid_cert;
bool valid_cn;
+ bool require_validation;
};
struct ustream_ssl_ctx;
@@ -58,17 +59,19 @@ struct ustream_ssl_ops {
int (*set_peer_cn)(struct ustream_ssl *conn, const char *name);
int (*context_set_ciphers)(struct ustream_ssl_ctx *ctx, const char *ciphers);
+ int (*context_set_require_validation)(struct ustream_ssl_ctx *ctx, bool require);
};
extern const struct ustream_ssl_ops ustream_ssl_ops;
-#define ustream_ssl_context_new ustream_ssl_ops.context_new
-#define ustream_ssl_context_set_crt_file ustream_ssl_ops.context_set_crt_file
-#define ustream_ssl_context_set_key_file ustream_ssl_ops.context_set_key_file
-#define ustream_ssl_context_add_ca_crt_file ustream_ssl_ops.context_add_ca_crt_file
-#define ustream_ssl_context_set_ciphers ustream_ssl_ops.context_set_ciphers
-#define ustream_ssl_context_free ustream_ssl_ops.context_free
-#define ustream_ssl_init ustream_ssl_ops.init
-#define ustream_ssl_set_peer_cn ustream_ssl_ops.set_peer_cn
+#define ustream_ssl_context_new ustream_ssl_ops.context_new
+#define ustream_ssl_context_set_crt_file ustream_ssl_ops.context_set_crt_file
+#define ustream_ssl_context_set_key_file ustream_ssl_ops.context_set_key_file
+#define ustream_ssl_context_add_ca_crt_file ustream_ssl_ops.context_add_ca_crt_file
+#define ustream_ssl_context_set_ciphers ustream_ssl_ops.context_set_ciphers
+#define ustream_ssl_context_set_require_validation ustream_ssl_ops.context_set_require_validation
+#define ustream_ssl_context_free ustream_ssl_ops.context_free
+#define ustream_ssl_init ustream_ssl_ops.init
+#define ustream_ssl_set_peer_cn ustream_ssl_ops.set_peer_cn
#endif
More information about the openwrt-devel
mailing list