bearssl: fix connect error on expired cert and no verify

- When peer verification is disabled use the x509_decode engine instead
  of the x509_minimal engine to parse and extract the public key from
  the first cert of the chain.

Prior to this change in such a case no key was extracted and that caused
CURLE_SSL_CONNECT_ERROR. The x509_minimal engine will stop parsing if
any validity check fails but the x509_decode won't.

Ref: https://github.com/curl/curl/pull/8106

Closes https://github.com/curl/curl/pull/8475
This commit is contained in:
Jan Venekamp 2021-12-06 18:36:01 +01:00 committed by Jay Satiro
parent b84437194c
commit 8af1cef29e

View File

@ -39,8 +39,10 @@
struct x509_context {
const br_x509_class *vtable;
br_x509_minimal_context minimal;
br_x509_decoder_context decoder;
bool verifyhost;
bool verifypeer;
int cert_num;
};
struct ssl_backend_data {
@ -260,6 +262,11 @@ static void x509_start_chain(const br_x509_class **ctx,
{
struct x509_context *x509 = (struct x509_context *)ctx;
if(!x509->verifypeer) {
x509->cert_num = 0;
return;
}
if(!x509->verifyhost)
server_name = NULL;
x509->minimal.vtable->start_chain(&x509->minimal.vtable, server_name);
@ -269,6 +276,13 @@ static void x509_start_cert(const br_x509_class **ctx, uint32_t length)
{
struct x509_context *x509 = (struct x509_context *)ctx;
if(!x509->verifypeer) {
/* Only decode the first cert in the chain to obtain the public key */
if(x509->cert_num == 0)
br_x509_decoder_init(&x509->decoder, NULL, NULL);
return;
}
x509->minimal.vtable->start_cert(&x509->minimal.vtable, length);
}
@ -277,6 +291,12 @@ static void x509_append(const br_x509_class **ctx, const unsigned char *buf,
{
struct x509_context *x509 = (struct x509_context *)ctx;
if(!x509->verifypeer) {
if(x509->cert_num == 0)
br_x509_decoder_push(&x509->decoder, buf, len);
return;
}
x509->minimal.vtable->append(&x509->minimal.vtable, buf, len);
}
@ -284,21 +304,23 @@ static void x509_end_cert(const br_x509_class **ctx)
{
struct x509_context *x509 = (struct x509_context *)ctx;
if(!x509->verifypeer) {
x509->cert_num++;
return;
}
x509->minimal.vtable->end_cert(&x509->minimal.vtable);
}
static unsigned x509_end_chain(const br_x509_class **ctx)
{
struct x509_context *x509 = (struct x509_context *)ctx;
unsigned err;
err = x509->minimal.vtable->end_chain(&x509->minimal.vtable);
if(err && !x509->verifypeer) {
/* ignore any X.509 errors */
err = BR_ERR_OK;
if(!x509->verifypeer) {
return br_x509_decoder_last_error(&x509->decoder);
}
return err;
return x509->minimal.vtable->end_chain(&x509->minimal.vtable);
}
static const br_x509_pkey *x509_get_pkey(const br_x509_class *const *ctx,
@ -306,6 +328,15 @@ static const br_x509_pkey *x509_get_pkey(const br_x509_class *const *ctx,
{
struct x509_context *x509 = (struct x509_context *)ctx;
if(!x509->verifypeer) {
/* Nothing in the chain is verified, just return the public key of the
first certificate and allow its usage for both TLS_RSA_* and
TLS_ECDHE_* */
if(usages)
*usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN;
return br_x509_decoder_get_pkey(&x509->decoder);
}
return x509->minimal.vtable->get_pkey(&x509->minimal.vtable, usages);
}