[openssl-users] Problems verifying OCSP signatures

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[openssl-users] Problems verifying OCSP signatures

Richard Moore
Hi All,

I'm trying to get some code to verify the signature of an OCSP response to
work properly and I'm hitting quite a few road blocks. I've also been talking
to the curl developers who are having the same problems and I wondered if
anyone can help us.

I've tried 3 different ways of handling the verification and none of them seem
to work reliably. All 3 work properly for checking the OCSP status of
www.google.com, but they all fail when testing revoked.grc.com and tn123.org.
I'm sure I must be doing something wrong, but I've no idea what and there
seems to be very little documentation in this area. I've put the 3 approaches
I've tried below in case anyone has any ideas. Note that the reason all the
openssl symbols has a q_XXX prefix is just due to a dlopen shim and doesn't
change the behaviour of the functions at all.

If anyone has any suggestions of what I'm doing wrong then please let me know.

Thanks

Rich.

/**
 * This version takes the whole issuer chain, and adds them as intermediates.
 * It also sets up the CA store.
 */
bool QSslOcspReply::hasValidSignature1(const QList<QSslCertificate> &issuers) const
{
    // Create the certificate store
    X509_STORE *certStore = q_X509_STORE_new();
    if (!certStore) {
        qWarning() << "Unable to create certificate store";
        return false;
    }

    // Build a stack to put the issuer in
    STACK_OF(X509) *intermediates = 0;
    intermediates = (STACK_OF(X509) *) q_sk_new_null();

    if (!intermediates) {
        q_X509_STORE_free(certStore);
        return false;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#else
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#endif

    foreach (const QSslCertificate &caCertificate, QSslSocket::defaultCaCertificates())
        q_X509_STORE_add_cert(certStore, (X509 *)caCertificate.handle());

    int verifyResult = q_OCSP_basic_verify(d->basicresp, intermediates, certStore, OCSP_TRUSTOTHER);

    // A verify result is a failure if it is 0 or less
    if (verifyResult <= 0) {
        unsigned long errnum = q_ERR_get_error();
        const char *error = q_ERR_error_string(errnum, 0);

        qDebug() << "OCSP response verification failed" << verifyResult;
        qDebug() << "Error was: " << error;
        // ### TODO: Fix mem leak
        return false;
    }
    qDebug() << "OCSP response verification good";

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_free( (_STACK *) intermediates);
#else
    q_sk_free( (STACK *) intermediates);
#endif
    q_X509_STORE_free(certStore);

    return true;
}

/**
 * This version takes the whole issuer chain, and adds them as intermediates.
 * It does not set up any CAs.
 */
bool QSslOcspReply::hasValidSignature2(const QList<QSslCertificate> &issuers) const
{
    // Create the certificate store
    X509_STORE *certStore = q_X509_STORE_new();
    if (!certStore) {
        qWarning() << "Unable to create certificate store";
        return false;
    }

    // Build a stack to put the issuer in
    STACK_OF(X509) *intermediates = 0;
    intermediates = (STACK_OF(X509) *) q_sk_new_null();

    if (!intermediates) {
        q_X509_STORE_free(certStore);
        return false;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#else
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#endif

    int verifyResult = q_OCSP_basic_verify(d->basicresp, intermediates, certStore, OCSP_TRUSTOTHER);

    // A verify result is a failure if it is 0 or less
    if (verifyResult <= 0) {
        unsigned long errnum = q_ERR_get_error();
        const char *error = q_ERR_error_string(errnum, 0);

        qDebug() << "OCSP response verification failed" << verifyResult;
        qDebug() << "Error was: " << error;
        // ### TODO: Fix mem leak
        return false;
    }
    qDebug() << "OCSP response verification good";

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_free( (_STACK *) intermediates);
#else
    q_sk_free( (STACK *) intermediates);
#endif
    q_X509_STORE_free(certStore);

    return true;
}

/**
 * This version takes the just the actual issuer, and adds it as an intermediate.
 * It does not set up any CAs.
 */
bool QSslOcspReply::hasValidSignature3(const QSslCertificate &issuer) const
{
    // Create the certificate store
    X509_STORE *certStore = q_X509_STORE_new();
    if (!certStore) {
        qWarning() << "Unable to create certificate store";
        return false;
    }

    // Build a stack to put the issuer in
    STACK_OF(X509) *intermediates = 0;
    intermediates = (STACK_OF(X509) *) q_sk_new_null();

    if (!intermediates) {
        q_X509_STORE_free(certStore);
        return false;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(issuer.handle()));
#else
    q_sk_push( (STACK *)intermediates, reinterpret_cast<X509 *>(issuer.handle()));
#endif

    int verifyResult = q_OCSP_basic_verify(d->basicresp, intermediates, certStore, OCSP_TRUSTOTHER);

    // A verify result is a failure if it is 0 or less
    if (verifyResult <= 0) {
        unsigned long errnum = q_ERR_get_error();
        const char *error = q_ERR_error_string(errnum, 0);

        qDebug() << "OCSP response verification failed" << verifyResult;
        qDebug() << "Error was: " << error;
        // ### TODO: Fix mem leak
        return false;
    }
    qDebug() << "OCSP response verification good";

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_free( (_STACK *) intermediates);
#else
    q_sk_free( (STACK *) intermediates);
#endif
    q_X509_STORE_free(certStore);

    return true;
}


_______________________________________________
openssl-users mailing list
[hidden email]
https://mta.opensslfoundation.net/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: [openssl-users] Problems verifying OCSP signatures

Richard Moore
I've now got this working, though to do so I seem to have to take the certificates supplied in the OCSP response directly out of the certs field of the OCSP_BASICRESP and add these as intermediates for the verification too. It feels bad to directly access the internals of this struct but there doesn't seem to be another way (unless someone can enlighten me).

Cheers

Rich.

On 28 December 2014 at 16:42, Richard Moore <[hidden email]> wrote:
Hi All,

I'm trying to get some code to verify the signature of an OCSP response to
work properly and I'm hitting quite a few road blocks. I've also been talking
to the curl developers who are having the same problems and I wondered if
anyone can help us.

I've tried 3 different ways of handling the verification and none of them seem
to work reliably. All 3 work properly for checking the OCSP status of
www.google.com, but they all fail when testing revoked.grc.com and tn123.org.
I'm sure I must be doing something wrong, but I've no idea what and there
seems to be very little documentation in this area. I've put the 3 approaches
I've tried below in case anyone has any ideas. Note that the reason all the
openssl symbols has a q_XXX prefix is just due to a dlopen shim and doesn't
change the behaviour of the functions at all.

If anyone has any suggestions of what I'm doing wrong then please let me know.

Thanks

Rich.

/**
 * This version takes the whole issuer chain, and adds them as intermediates.
 * It also sets up the CA store.
 */
bool QSslOcspReply::hasValidSignature1(const QList<QSslCertificate> &issuers) const
{
    // Create the certificate store
    X509_STORE *certStore = q_X509_STORE_new();
    if (!certStore) {
        qWarning() << "Unable to create certificate store";
        return false;
    }

    // Build a stack to put the issuer in
    STACK_OF(X509) *intermediates = 0;
    intermediates = (STACK_OF(X509) *) q_sk_new_null();

    if (!intermediates) {
        q_X509_STORE_free(certStore);
        return false;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#else
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#endif

    foreach (const QSslCertificate &caCertificate, QSslSocket::defaultCaCertificates())
        q_X509_STORE_add_cert(certStore, (X509 *)caCertificate.handle());

    int verifyResult = q_OCSP_basic_verify(d->basicresp, intermediates, certStore, OCSP_TRUSTOTHER);

    // A verify result is a failure if it is 0 or less
    if (verifyResult <= 0) {
        unsigned long errnum = q_ERR_get_error();
        const char *error = q_ERR_error_string(errnum, 0);

        qDebug() << "OCSP response verification failed" << verifyResult;
        qDebug() << "Error was: " << error;
        // ### TODO: Fix mem leak
        return false;
    }
    qDebug() << "OCSP response verification good";

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_free( (_STACK *) intermediates);
#else
    q_sk_free( (STACK *) intermediates);
#endif
    q_X509_STORE_free(certStore);

    return true;
}

/**
 * This version takes the whole issuer chain, and adds them as intermediates.
 * It does not set up any CAs.
 */
bool QSslOcspReply::hasValidSignature2(const QList<QSslCertificate> &issuers) const
{
    // Create the certificate store
    X509_STORE *certStore = q_X509_STORE_new();
    if (!certStore) {
        qWarning() << "Unable to create certificate store";
        return false;
    }

    // Build a stack to put the issuer in
    STACK_OF(X509) *intermediates = 0;
    intermediates = (STACK_OF(X509) *) q_sk_new_null();

    if (!intermediates) {
        q_X509_STORE_free(certStore);
        return false;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#else
    foreach (const QSslCertificate &cert, issuers)
        q_sk_push( (STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#endif

    int verifyResult = q_OCSP_basic_verify(d->basicresp, intermediates, certStore, OCSP_TRUSTOTHER);

    // A verify result is a failure if it is 0 or less
    if (verifyResult <= 0) {
        unsigned long errnum = q_ERR_get_error();
        const char *error = q_ERR_error_string(errnum, 0);

        qDebug() << "OCSP response verification failed" << verifyResult;
        qDebug() << "Error was: " << error;
        // ### TODO: Fix mem leak
        return false;
    }
    qDebug() << "OCSP response verification good";

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_free( (_STACK *) intermediates);
#else
    q_sk_free( (STACK *) intermediates);
#endif
    q_X509_STORE_free(certStore);

    return true;
}

/**
 * This version takes the just the actual issuer, and adds it as an intermediate.
 * It does not set up any CAs.
 */
bool QSslOcspReply::hasValidSignature3(const QSslCertificate &issuer) const
{
    // Create the certificate store
    X509_STORE *certStore = q_X509_STORE_new();
    if (!certStore) {
        qWarning() << "Unable to create certificate store";
        return false;
    }

    // Build a stack to put the issuer in
    STACK_OF(X509) *intermediates = 0;
    intermediates = (STACK_OF(X509) *) q_sk_new_null();

    if (!intermediates) {
        q_X509_STORE_free(certStore);
        return false;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(issuer.handle()));
#else
    q_sk_push( (STACK *)intermediates, reinterpret_cast<X509 *>(issuer.handle()));
#endif

    int verifyResult = q_OCSP_basic_verify(d->basicresp, intermediates, certStore, OCSP_TRUSTOTHER);

    // A verify result is a failure if it is 0 or less
    if (verifyResult <= 0) {
        unsigned long errnum = q_ERR_get_error();
        const char *error = q_ERR_error_string(errnum, 0);

        qDebug() << "OCSP response verification failed" << verifyResult;
        qDebug() << "Error was: " << error;
        // ### TODO: Fix mem leak
        return false;
    }
    qDebug() << "OCSP response verification good";

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    q_sk_free( (_STACK *) intermediates);
#else
    q_sk_free( (STACK *) intermediates);
#endif
    q_X509_STORE_free(certStore);

    return true;
}



_______________________________________________
openssl-users mailing list
[hidden email]
https://mta.opensslfoundation.net/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: [openssl-users] Problems verifying OCSP signatures

Walter H.
On 03.01.2015 18:16, Richard Moore wrote:
I've now got this working, though to do so I seem to have to take the certificates supplied in the OCSP response directly out of the certs field of the OCSP_BASICRESP and add these as intermediates for the verification too. It feels bad to directly access the internals of this struct but there doesn't seem to be another way (unless someone can enlighten me).

Cheers

Rich.
the certificate you want to test its validity with OCSP has the same intermediate CA cert. as the OCSP responder certificate you use in OCSP response

Walter

_______________________________________________
openssl-users mailing list
[hidden email]
https://mta.opensslfoundation.net/mailman/listinfo/openssl-users

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [openssl-users] Problems verifying OCSP signatures

Richard Moore


On 3 January 2015 at 21:45, Walter H. <[hidden email]> wrote:
On 03.01.2015 18:16, Richard Moore wrote:
I've now got this working, though to do so I seem to have to take the certificates supplied in the OCSP response directly out of the certs field of the OCSP_BASICRESP and add these as intermediates for the verification too. It feels bad to directly access the internals of this struct but there doesn't seem to be another way (unless someone can enlighten me).

Cheers

Rich.
the certificate you want to test its validity with OCSP has the same intermediate CA cert. as the OCSP responder certificate you use in OCSP response

Simply specifying the intermediates from the certificate chain of the server doesn't appear to actually work - that's what I tried first. Sadly I've not seen any documentation or examples of how to use this part of openssl.

Cheers

Rich.
 

_______________________________________________
openssl-users mailing list
[hidden email]
https://mta.opensslfoundation.net/mailman/listinfo/openssl-users