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; } -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mta.opensslfoundation.net/pipermail/openssl-users/attachments/20141228/a116b024/attachment.html>