Working inside X509_STORE_CTX using verification callbacks

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Working inside X509_STORE_CTX using verification callbacks

Simon Edwards

Hello Everyone.

 

I am migrating code written to the old 1.0 (actually probably more like 0.9.?) X509_STORE API which has a replacement for the check_issuer callback function.

 

Unless I am missing something the 1.1.1c SDK’s public API is missing some accessor functions that are required for a like-for-like update to 1.1.1c.

 

    void X509_STORE_CTX_set0_current_issuer(X509_STORE_CTX *ctx, X509 *cert){

       ctx->current_issuer = cert;

  }

    void X509_STORE_CTX_set0_error(X509_STORE_CTX *ctx, int error) {

       ctx->error = error;

   }

 

I suspect I will need to build this as an internal OpenSSL source module in order to allow access inside the STORE structure.

 

Or, have I missed a replacement API somewhere?

 

The reason for using our own callback function is to allow for the situation where a trustpoint collection may contain multiple certificates with the same DN but different keys. The second (or later) of these may be the signer of the certificate being verified.  The OpenSSL version would stop when it encountered the first certificate with an incorrect key. If OpenSSL now supports this situation we could remove the need to set our own callback.

 

 

Simon Edwards
Principal Software Engineer

 

Micro Focus

[hidden email]

The Lawn, 22-30 Old Bath Road
Newbury, Berkshire, UK

Shoretel 44224
Direct: +44 1635 565487

 

Reply | Threaded
Open this post in threaded view
|

Re: Working inside X509_STORE_CTX using verification callbacks

Matt Caswell-2


On 25/09/2019 12:22, Simon Edwards wrote:
>     void X509_STORE_CTX_set0_error(X509_STORE_CTX *ctx, int error) {
>
>        ctx->error = error;
>
>    }

This one already exists:

void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
{
    ctx->error = err;
}

Other missing accessors could be added (and even backported to stable releases)
if there is a strong enough justification for wanting them.

Matt
Reply | Threaded
Open this post in threaded view
|

RE: Working inside X509_STORE_CTX using verification callbacks

Simon Edwards
In reply to this post by Simon Edwards

Okay.

 

Thanks Matt, I didn’t see that one in x509_vfy.c, I must look harder.

 

 

I will modify our own copy of OpenSSL1.1.1c to provide the missing functions and open a PR on the master.

 

Simon Edwards

 

On 25/09/2019 12:31, Matt Caswell wrote:

 

On 25/09/2019 12:22, Simon Edwards wrote:

>     void X509_STORE_CTX_set0_error(X509_STORE_CTX *ctx, int error) {

>

>        ctx->error = error;

>

>    }

 

This one already exists:

 

void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)

{

    ctx->error = err;

}

 

Other missing accessors could be added (and even backported to stable releases)

if there is a strong enough justification for wanting them.

 

Matt

 

 

From: Simon Edwards
Sent: 25 September 2019 12:22
To: [hidden email]
Subject: Working inside X509_STORE_CTX using verification callbacks

 

Hello Everyone.

 

I am migrating code written to the old 1.0 (actually probably more like 0.9.?) X509_STORE API which has a replacement for the check_issuer callback function.

 

Unless I am missing something the 1.1.1c SDK’s public API is missing some accessor functions that are required for a like-for-like update to 1.1.1c.

 

    void X509_STORE_CTX_set0_current_issuer(X509_STORE_CTX *ctx, X509 *cert){

       ctx->current_issuer = cert;

  }

    void X509_STORE_CTX_set0_error(X509_STORE_CTX *ctx, int error) {

       ctx->error = error;

   }

 

I suspect I will need to build this as an internal OpenSSL source module in order to allow access inside the STORE structure.

 

Or, have I missed a replacement API somewhere?

 

The reason for using our own callback function is to allow for the situation where a trustpoint collection may contain multiple certificates with the same DN but different keys. The second (or later) of these may be the signer of the certificate being verified.  The OpenSSL version would stop when it encountered the first certificate with an incorrect key. If OpenSSL now supports this situation we could remove the need to set our own callback.

 

 

Simon Edwards
Principal Software Engineer

 

Micro Focus

[hidden email]

The Lawn, 22-30 Old Bath Road
Newbury, Berkshire, UK

Shoretel 44224
Direct: +44 1635 565487

 

Reply | Threaded
Open this post in threaded view
|

Re: Working inside X509_STORE_CTX using verification callbacks

Viktor Dukhovni
In reply to this post by Simon Edwards
On Wed, Sep 25, 2019 at 11:22:26AM +0000, Simon Edwards wrote:

>   void X509_STORE_CTX_set0_current_issuer(X509_STORE_CTX *ctx, X509 *cert)
>   {
>        ctx->current_issuer = cert;
>   }

Can you provide a motivating use-case for this accessor?  In
verification callbacks this lets you peek not only at the current
certificate, but also its issuer, but setting this has no useful
side-effects.

I've not looked at the CRL check code closely enough to know whether
there's a use-case there, but at first glance it looks unlikely.

--
        Viktor.
Reply | Threaded
Open this post in threaded view
|

RE: Working inside X509_STORE_CTX using verification callbacks

Michael Wojcik
> From: openssl-users [mailto:[hidden email]] On Behalf Of
> Viktor Dukhovni
>
> On Wed, Sep 25, 2019 at 11:22:26AM +0000, Simon Edwards wrote:
>
> >   void X509_STORE_CTX_set0_current_issuer(X509_STORE_CTX *ctx, X509 *cert)
> >   {
> >        ctx->current_issuer = cert;
> >   }
>
> Can you provide a motivating use-case for this accessor?  In
> verification callbacks this lets you peek not only at the current
> certificate, but also its issuer, but setting this has no useful
> side-effects.

Simon may correct me on this, and it may not be useful anyway; but if memory serves, it's currently being used to set the issuer on one invocation of the callback, so that on subsequent invocations for the same certificate the callback will see the desired issuer. (The callback gets invoked once for each error that the library wants to raise regarding the certificate, doesn't it? It's been a while since I worked in this area.)

So I *think* this was being used to store the application's decision about the real issuer, when there were multiple root or intermediate certificates - generally to support an RSA keypair and a DSA keypair - with the same CN, and that part of the certificate chain lacked SKID/AKID extensions so the actual issuing certificate had to be determined by key type.

The application in question is actually middleware, and still has to deal with a lot of certificates that aren't v3 or otherwise don't conform to current best practice, and its trust-store configuration mechanism permits multiple trees with colliding subject DNs, so its callback contains some fairly convoluted logic to try to build a valid chain back to a trust anchor while imposing all the necessary checks to maintain security.

--
Michael Wojcik
Distinguished Engineer, Micro Focus


Reply | Threaded
Open this post in threaded view
|

Re: Working inside X509_STORE_CTX using verification callbacks

Viktor Dukhovni
On Wed, Sep 25, 2019 at 07:05:59PM +0000, Michael Wojcik wrote:

> Simon may correct me on this, and it may not be useful anyway; but if
> memory serves, it's currently being used to set the issuer on one invocation
> of the callback, so that on subsequent invocations for the same certificate
> the callback will see the desired issuer.

The "verify callback" is called for each error during chain
construction that does not cause immediate failure, and then, once
the chain is built, for each layer in the chain starting with the
trust-anchor reporting success or any signature or expiration issues.
This final pass sets the current issuer for inspection.

I would not expect the "verify callback" to construct an alternate
chain, for that, with SSL one would need to instead use
SSL_CTX_set_cert_verify_callback(3), which side-steps the entirety
of the built-in chain construction and verification process.  With
that you do whatever you want, but if you then want to also run the
normal verify callbacks from your own chain construction code,
then perhaps you might need an accessor to set the (read-only
from the perspective of those callbacks) issuer_cert.

--
        Viktor.