C++ Check OCSP For Cert Revocation



//g++ main.cpp -lcrypto
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
#include <openssl/crypto.h>
#include <openssl/ocsp.h>
#include <openssl/pem.h>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <string>
 
using std::cout;
using std::endl;
using std::stringstream;
using std::map;
using std::vector;
using std::string;
 
//----------------------------------------------------------------------
vector<string> ocsp_urls(X509 *x509)
{
    vector<string> list;
    STACK_OF(OPENSSL_STRING) *ocsp_list = X509_get1_ocsp(x509);
    for (int j = 0; j < sk_OPENSSL_STRING_num(ocsp_list); j++)
    {
        list.push_back( string( sk_OPENSSL_STRING_value(ocsp_list, j) ) ); 
    }
    X509_email_free(ocsp_list);
    return list;
}
//----------------------------------------------------------------------
int prepareRequest(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md,X509 *issuer,
                STACK_OF(OCSP_CERTID) *ids)
{
    OCSP_CERTID *id;
    if(!issuer)
        {
        std::cerr << "No issuer certificate specified" << endl;
        //BIO_printf(bio_err, "No issuer certificate specified\n");
        return 0;
        }
    if(!*req) *req = OCSP_REQUEST_new();
    if(!*req) goto err;
    id = OCSP_cert_to_id(cert_id_md, cert, issuer);
    if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
    if(!OCSP_request_add0_id(*req, id)) goto err;
    return 1;
 
    err:
        std::cerr << "Error Creating OCSP request" << endl;
        //BIO_printf(bio_err, "Error Creating OCSP request\n");
    return 0;
}
//----------------------------------------------------------------------
OCSP_RESPONSE * queryResponder(BIO *err, BIO *cbio, char *path,
                char *host, OCSP_REQUEST *req, int req_timeout)
{
    int fd;
    int rv;
    int i;
    OCSP_REQ_CTX *ctx = NULL;
    OCSP_RESPONSE *rsp = NULL;
    fd_set confds;
    struct timeval tv;
 
    if (req_timeout != -1)
        BIO_set_nbio(cbio, 1);
 
    rv = BIO_do_connect(cbio);
 
    if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio)))
        {
        std::cerr << "Error connecting BIO" << endl;
        return NULL;
        }
 
    if (BIO_get_fd(cbio, &fd) <= 0)
        {
        std::cerr << "Can't get connection fd" << endl;
        goto err;
        }
 
    if (req_timeout != -1 && rv <= 0)
        {
        FD_ZERO(&confds);
        FD_SET(fd, &confds);
        tv.tv_usec = 0;
        tv.tv_sec = req_timeout;
        rv = select(fd + 1, NULL, &confds, NULL, &tv);
        if (rv == 0)
            {
            std::cerr << "Timeout on connect" << endl;
            //BIO_puts(err, "Timeout on connect\n");
            return NULL;
            }
        }
 
    ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
    if (!ctx)
        return NULL;
 
    if (!OCSP_REQ_CTX_add1_header(ctx, "Host", host))
        goto err;
 
    if (!OCSP_REQ_CTX_set1_req(ctx, req))
        goto err;
 
    for (;;)
        {
        rv = OCSP_sendreq_nbio(&rsp, ctx);
        if (rv != -1)
            break;
        if (req_timeout == -1)
            continue;
        FD_ZERO(&confds);
        FD_SET(fd, &confds);
        tv.tv_usec = 0;
        tv.tv_sec = req_timeout;
        if (BIO_should_read(cbio))
            rv = select(fd + 1, &confds, NULL, NULL, &tv);
        else if (BIO_should_write(cbio))
            rv = select(fd + 1, NULL, &confds, NULL, &tv);
        else
            {
            std::cerr << "Unexpected retry condition" << endl;
            goto err;
            }
        if (rv == 0)
            {
            std::cerr << "Timeout on request" << endl;
            break;
            }
        if (rv == -1)
            {
            std::cerr << "Select error" << endl;
            break;
            }
 
        }
    err:
    if (ctx)
        OCSP_REQ_CTX_free(ctx);
 
    return rsp;
}
//----------------------------------------------------------------------
OCSP_RESPONSE * sendRequest(BIO *err, OCSP_REQUEST *req,
            char *host, char *path, char *port, int use_ssl,
            int req_timeout)
{
    BIO *cbio = NULL;
    OCSP_RESPONSE *resp = NULL;
    cbio = BIO_new_connect(host);
    if (cbio && port && use_ssl==0)
    {
        BIO_set_conn_port(cbio, port);
        resp = queryResponder(err, cbio, path, host, req, req_timeout);
        if (!resp)
            std::cerr << "Error querying OCSP responder" << endl;
    }
    if (cbio)
        BIO_free_all(cbio);
    return resp;
}
//----------------------------------------------------------------------
int parseResponse(OCSP_RESPONSE *resp)
{
    int is_revoked = -1;
    OCSP_RESPBYTES *rb = resp->responseBytes;
    if (rb && OBJ_obj2nid(rb->responseType) == NID_id_pkix_OCSP_basic)
    {
        OCSP_BASICRESP *br = OCSP_response_get1_basic(resp);
        OCSP_RESPDATA  *rd = br->tbsResponseData;
 
        for (int i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++)
        {
            OCSP_SINGLERESP *single = sk_OCSP_SINGLERESP_value(rd->responses, i);
            OCSP_CERTID *cid = single->certId;
            OCSP_CERTSTATUS *cst = single->certStatus;
            if (cst->type == V_OCSP_CERTSTATUS_REVOKED)
            {
                is_revoked = 1;
            }
            else if (cst->type == V_OCSP_CERTSTATUS_GOOD)
            {
                is_revoked = 0;
            }
        }
        OCSP_BASICRESP_free(br);
    }
    return is_revoked;
}
//----------------------------------------------------------------------
int checkCertOCSP(X509 *x509, X509 *issuer)
{
    int is_revoked=-1;
 
    BIO *bio_out = BIO_new_fp(stdout, BIO_NOCLOSE|BIO_FP_TEXT);
    BIO *bio_err = BIO_new_fp(stderr, BIO_NOCLOSE|BIO_FP_TEXT);
 
    if (issuer)
    {
        //build ocsp request
        OCSP_REQUEST *req = NULL;
        STACK_OF(CONF_VALUE) *headers = NULL;
        STACK_OF(OCSP_CERTID) *ids = sk_OCSP_CERTID_new_null();
        const EVP_MD *cert_id_md = EVP_sha1();
        prepareRequest(&req, x509, cert_id_md, issuer, ids);
 
        //loop through OCSP urls
        STACK_OF(OPENSSL_STRING) *ocsp_list = X509_get1_ocsp(x509);
        for (int j = 0; j < sk_OPENSSL_STRING_num(ocsp_list) && is_revoked==-1; j++)
        {
            char *host = NULL, *port = NULL, *path = NULL; 
            int use_ssl, req_timeout = 30;
            string ocsp_url0 = string( sk_OPENSSL_STRING_value(ocsp_list, j) );
 
            char *ocsp_url = sk_OPENSSL_STRING_value(ocsp_list, j);
            if (OCSP_parse_url(ocsp_url, &host, &port, &path, &use_ssl) && !use_ssl)
            {
                //send ocsp request
                OCSP_RESPONSE *resp = sendRequest(bio_err, req, host, path, port, use_ssl, req_timeout);
                if (resp)
                {
                                        //see crypto/ocsp/ocsp_prn.c for examples parsing OCSP responses
                    int responder_status = OCSP_response_status(resp);
 
                    //parse response
                    if (resp && responder_status == OCSP_RESPONSE_STATUS_SUCCESSFUL)
                    {
                        is_revoked = parseResponse(resp);
                    }
                    OCSP_RESPONSE_free(resp);
                }
            }
            OPENSSL_free(host);
            OPENSSL_free(path);
            OPENSSL_free(port);
        }
        X509_email_free(ocsp_list);
        OCSP_REQUEST_free(req);
    }
 
    BIO_free(bio_out);
    BIO_free(bio_err);
    return is_revoked;
}
//----------------------------------------------------------------------
string commonName(X509 *x509)
{
    X509_NAME *subject = X509_get_subject_name(x509);
    int subject_position = X509_NAME_get_index_by_NID(subject, NID_commonName, 0);
    X509_NAME_ENTRY *entry = subject_position==-1 ? NULL : X509_NAME_get_entry(subject, subject_position);
    ASN1_STRING *d = X509_NAME_ENTRY_get_data(entry);
    return string( (char*)ASN1_STRING_data(d), ASN1_STRING_length(d) );
}
//----------------------------------------------------------------------
void isRevokedByOCSP(const char cert_bytes[], const char issuer_bytes[])
{
    BIO *bio_mem1 = BIO_new(BIO_s_mem());
    BIO *bio_mem2 = BIO_new(BIO_s_mem());
    BIO_puts(bio_mem1, cert_bytes);
    BIO_puts(bio_mem2, issuer_bytes);
    X509 * x509 = PEM_read_bio_X509(bio_mem1, NULL, NULL, NULL);
    X509 * issuer = PEM_read_bio_X509(bio_mem2, NULL, NULL, NULL);
    cout << commonName(x509) << " certificate, ";
    cout << "isRevokedByOCSP: " << checkCertOCSP(x509, issuer) << endl;
    BIO_free(bio_mem1);
    BIO_free(bio_mem2);
    X509_free(x509);
    X509_free(issuer);
}
//----------------------------------------------------------------------
 
 
 
 
//----------------------------------------------------------------------
int main(int argc, char **argv)
{
    OpenSSL_add_all_algorithms();
 
    const char cert1_bytes[] = "-----BEGIN CERTIFICATE-----" "\n"
"MIIDszCCAzigAwIBAgIQDGv40oFewTIKpCtIVTYSOTAKBggqhkjOPQQDAjBMMQsw" "\n"
"CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSYwJAYDVQQDEx1EaWdp" "\n"
"Q2VydCBFQ0MgU2VjdXJlIFNlcnZlciBDQTAeFw0xNTA3MjgwMDAwMDBaFw0xNjA5" "\n"
"MzAxMjAwMDBaMHQxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhJbGxpbm9pczEQMA4G" "\n"
"A1UEBxMHQ2hpY2FnbzEoMCYGA1UEChMfWmFja3MgSW52ZXN0bWVudCBSZXNlYXJj" "\n"
"aCwgSW5jLjEWMBQGA1UEAxMNd3d3LnphY2tzLmNvbTBZMBMGByqGSM49AgEGCCqG" "\n"
"SM49AwEHA0IABOYOkwbEkkL/xKRUFV8xIfXYm5G/CnwpopbjZaLki/buATo2eSNd" "\n"
"0gPYzhzrfpd9HWV34Z/kO/yocvpbOTFrNDijggHSMIIBzjAfBgNVHSMEGDAWgBSj" "\n"
"neYf+do5T8Bu6JHLlaXaMeIKnzAdBgNVHQ4EFgQUtGr+7XN7qK4ZmnEDBNn7V+YI" "\n"
"QU0wIwYDVR0RBBwwGoINd3d3LnphY2tzLmNvbYIJemFja3MuY29tMA4GA1UdDwEB" "\n"
"/wQEAwIDiDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwaQYDVR0fBGIw" "\n"
"YDAuoCygKoYoaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2EtZWNjLWcxLmNy" "\n"
"bDAuoCygKoYoaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2EtZWNjLWcxLmNy" "\n"
"bDBCBgNVHSAEOzA5MDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczov" "\n"
"L3d3dy5kaWdpY2VydC5jb20vQ1BTMHsGCCsGAQUFBwEBBG8wbTAkBggrBgEFBQcw" "\n"
"AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEUGCCsGAQUFBzAChjlodHRwOi8v" "\n"
"Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRFQ0NTZWN1cmVTZXJ2ZXJDQS5j" "\n"
"cnQwDAYDVR0TAQH/BAIwADAKBggqhkjOPQQDAgNpADBmAjEA2vqnY3CyBs18df3H" "\n"
"h+DJBj8t91Ix6DKdJdrJg/HiPtg9EwQ8TRwZ5Fg4HgTmNaTiAjEAxzYXnrz9tK9N" "\n"
"DEh5AG+tvna+rzsBwEAh/rBPXeFQx2uCt9deviww57Eg4pSx5cBL" "\n"
"-----END CERTIFICATE-----" "\n";
 
    const char issuer1_bytes[] = "-----BEGIN CERTIFICATE-----" "\n"
"MIIDrDCCApSgAwIBAgIQCssoukZe5TkIdnRw883GEjANBgkqhkiG9w0BAQwFADBh" "\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3" "\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD" "\n"
"QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaMEwxCzAJBgNVBAYTAlVT" "\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJjAkBgNVBAMTHURpZ2lDZXJ0IEVDQyBT" "\n"
"ZWN1cmUgU2VydmVyIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4ghC6nfYJN6g" "\n"
"LGSkE85AnCNyqQIKDjc/ITa4jVMU9tWRlUvzlgKNcR7E2Munn17voOZ/WpIRllNv" "\n"
"68DLP679Wz9HJOeaBy6Wvqgvu1cYr3GkvXg6HuhbPGtkESvMNCuMo4IBITCCAR0w" "\n"
"EgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwNAYIKwYBBQUHAQEE" "\n"
"KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQgYDVR0f" "\n"
"BDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xv" "\n"
"YmFsUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYc" "\n"
"aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUo53mH/naOU/A" "\n"
"buiRy5Wl2jHiCp8wHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJ" "\n"
"KoZIhvcNAQEMBQADggEBAMeKoENL7HTJxavVHzA1Nm6YVntIrAVjrnuaVyRXzG/6" "\n"
"3qttnMe2uuzO58pzZNvfBDcKAEmzP58mrZGMIOgfiA4q+2Y3yDDo0sIkp0VILeoB" "\n"
"UEoxlBPfjV/aKrtJPGHzecicZpIalir0ezZYoyxBEHQa0+1IttK7igZFcTMQMHp6" "\n"
"mCHdJLnsnLWSB62DxsRq+HfmNb4TDydkskO/g+l3VtsIh5RHFPVfKK+jaEyDj2D3" "\n"
"loB5hWp2Jp2VDCADjT7ueihlZGak2YPqmXTNbk19HOuNssWvFhtOyPNV6og4ETQd" "\n"
"Ea8/B6hPatJ0ES8q/HO3X8IVQwVs1n3aAr0im0/T+Xc=" "\n"
"-----END CERTIFICATE-----" "\n";
 
    const char cert2_bytes[] = "-----BEGIN CERTIFICATE-----" "\n"
"MIIFCjCCA/KgAwIBAgIQdPwLZPmx/EfhJqUTOWRNaTANBgkqhkiG9w0BAQUFADBz" "\n"
"MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD" "\n"
"VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEZMBcGA1UE" "\n"
"AxMQUG9zaXRpdmVTU0wgQ0EgMjAeFw0xNDAzMTEwMDAwMDBaFw0xOTAzMTAyMzU5" "\n"
"NTlaMFYxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEUMBIGA1UE" "\n"
"CxMLUG9zaXRpdmVTU0wxGzAZBgNVBAMTEm96Y29tcHV0ZXJzLmNvbS5hdTCCASIw" "\n"
"DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmybPUeo6tsDuuXNJ2uatedHZCR" "\n"
"duHtcTXTzURJ6yIUdwVJ4gkI+0w/gqVRBEA748M1boYeBWJOeMdyTjpkopqJD49S" "\n"
"BOSi2MhEEmfXQpKXmFz6n0WKaHnn8Aa1Vlo1+EEzskJ8KFY0j5VEG/itCvBhXd1j" "\n"
"xN7GzCqh62M7CpIprpfzHXj8cv7HQ1H57mMosLYo6dmBUfDfuBqHxy64vl06B3DI" "\n"
"Z9+3fZl30PQb2dpHywkAvg1gmI0BhJK+ONdz0oEhniNFS67FMbomNr3VAsy32sNG" "\n"
"6pIn72r/iynXCt8EeC8HsIzcVZRSnpKWUPBc4qsXh2vXb8Emg6pXm7PDrRECAwEA" "\n"
"AaOCAbUwggGxMB8GA1UdIwQYMBaAFJnkQF9rFF4+Bdnd02NU/GK49wCsMB0GA1Ud" "\n"
"DgQWBBTq+Z3M1D1E/IAZSABGYIQwJw5uKzAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0T" "\n"
"AQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwUAYDVR0gBEkw" "\n"
"RzA7BgsrBgEEAbIxAQICBzAsMCoGCCsGAQUFBwIBFh5odHRwOi8vd3d3LnBvc2l0" "\n"
"aXZlc3NsLmNvbS9DUFMwCAYGZ4EMAQIBMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6" "\n"
"Ly9jcmwuY29tb2RvY2EuY29tL1Bvc2l0aXZlU1NMQ0EyLmNybDBsBggrBgEFBQcB" "\n"
"AQRgMF4wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL1Bvc2l0" "\n"
"aXZlU1NMQ0EyLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2Eu" "\n"
"Y29tMDUGA1UdEQQuMCyCEm96Y29tcHV0ZXJzLmNvbS5hdYIWd3d3Lm96Y29tcHV0" "\n"
"ZXJzLmNvbS5hdTANBgkqhkiG9w0BAQUFAAOCAQEA45yd7ccirosItEYH9pP/GEBu" "\n"
"Zllsb3vPTZa/DcEq2hY+Hwuc+Dd6caJp9hwQIEXKgb1CJb1xNpAUnmaeH5jyOhXp" "\n"
"AobpC/hfstgiiOGrPF2bp2lx33pi6uyLjtPS8WQK1bXJbO8FJoNRZc+nbswU0asq" "\n"
"HdG4Su9fNjfBs8V4TW9X7kItOqpslNHyaS2TUF1aJWVFcORez5S1O/WiXZMP6yGt" "\n"
"ars8VZh8eHoy+TSwS7lrjBFEq4QXvaYf1L8RBLWF+uLWk5RJr9UA0H/G+CP+G1Mw" "\n"
"fHi5+er4glz2RtZFbo1xQjSPzvjBbZ6RPVurMQ+ukKN1G2rMJeBykgB9gl5Tiw==" "\n"
"-----END CERTIFICATE-----" "\n";
 
    const char issuer2_bytes[] = "-----BEGIN CERTIFICATE-----" "\n"
"MIIE5TCCA82gAwIBAgIQB28SRoFFnCjVSNaXxA4AGzANBgkqhkiG9w0BAQUFADBv" "\n"
"MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk" "\n"
"ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF" "\n"
"eHRlcm5hbCBDQSBSb290MB4XDTEyMDIxNjAwMDAwMFoXDTIwMDUzMDEwNDgzOFow" "\n"
"czELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G" "\n"
"A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxGTAXBgNV" "\n"
"BAMTEFBvc2l0aXZlU1NMIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK" "\n"
"AoIBAQDo6jnjIqaqucQA0OeqZztDB71Pkuu8vgGjQK3g70QotdA6voBUF4V6a4Rs" "\n"
"NjbloyTi/igBkLzX3Q+5K05IdwVpr95XMLHo+xoD9jxbUx6hAUlocnPWMytDqTcy" "\n"
"Ug+uJ1YxMGCtyb1zLDnukNh1sCUhYHsqfwL9goUfdE+SNHNcHQCgsMDqmOK+ARRY" "\n"
"FygiinddUCXNmmym5QzlqyjDsiCJ8AckHpXCLsDl6ez2PRIHSD3SwyNWQezT3zVL" "\n"
"yOf2hgVSEEOajBd8i6q8eODwRTusgFX+KJPhChFo9FJXb/5IC1tdGmpnc5mCtJ5D" "\n"
"YD7HWyoSbhruyzmuwzWdqLxdsC/DAgMBAAGjggF3MIIBczAfBgNVHSMEGDAWgBSt" "\n"
"vZh6NLQm9/rEJlTvA73gJMtUGjAdBgNVHQ4EFgQUmeRAX2sUXj4F2d3TY1T8Yrj3" "\n"
"AKwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEQYDVR0gBAow" "\n"
"CDAGBgRVHSAAMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0" "\n"
"LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDCBswYIKwYBBQUHAQEEgaYw" "\n"
"gaMwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9BZGRUcnVz" "\n"
"dEV4dGVybmFsQ0FSb290LnA3YzA5BggrBgEFBQcwAoYtaHR0cDovL2NydC51c2Vy" "\n"
"dHJ1c3QuY29tL0FkZFRydXN0VVROU0dDQ0EuY3J0MCUGCCsGAQUFBzABhhlodHRw" "\n"
"Oi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQCcNuNOrvGK" "\n"
"u2yXjI9LZ9Cf2ISqnyFfNaFbxCtjDei8d12nxDf9Sy2e6B1pocCEzNFti/OBy59L" "\n"
"dLBJKjHoN0DrH9mXoxoR1Sanbg+61b4s/bSRZNy+OxlQDXqV8wQTqbtHD4tc0azC" "\n"
"e3chUN1bq+70ptjUSlNrTa24yOfmUlhNQ0zCoiNPDsAgOa/fT0JbHtMJ9BgJWSrZ" "\n"
"6EoYvzL7+i1ki4fKWyvouAt+vhcSxwOCKa9Yr4WEXT0K3yNRw82vEL+AaXeRCk/l" "\n"
"uuGtm87fM04wO+mPZn+C+mv626PAcwDj1hKvTfIPWhRRH224hoFiB85ccsJP81cq" "\n"
"cdnUl4XmGFO3" "\n"
"-----END CERTIFICATE-----" "\n";
 
    isRevokedByOCSP(cert1_bytes, issuer1_bytes);
    isRevokedByOCSP(cert2_bytes, issuer2_bytes);
}
//----------------------------------------------------------------------
code snippets are licensed under Creative Commons CC-By-SA 3.0 (unless otherwise specified)