| /* |
| * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. |
| * |
| * Licensed under the Apache License 2.0 (the "License"). You may not use |
| * this file except in compliance with the License. You can obtain a copy |
| * in the file LICENSE in the source distribution or at |
| * https://www.openssl.org/source/license.html |
| */ |
| |
| #include <time.h> |
| #include <openssl/bio.h> |
| #include <openssl/crypto.h> |
| #include <openssl/err.h> |
| #include <openssl/pem.h> |
| #include <openssl/x509.h> |
| #include <openssl/x509_vfy.h> |
| #ifndef OPENSSL_NO_OCSP |
| #include <openssl/ocsp.h> |
| #endif |
| |
| #include "testutil.h" |
| |
| #ifndef OPENSSL_NO_OCSP |
| |
| /* |
| * Fixtures for the OCSP stapled-response verification path |
| * (check_cert_ocsp_resp() in x509_vfy.c), reached from X509_verify_cert() |
| * when X509_V_FLAG_OCSP_RESP_CHECK is set and responses are attached with |
| * X509_STORE_CTX_set_ocsp_resp(). |
| * |
| * Root CA (self-signed trust anchor) |
| * \-- leaf (signed by the Root CA) |
| * |
| * The flat chain makes the root both the trust anchor and the authorized OCSP |
| * responder for the leaf, and having the root key lets each test build its own |
| * signed responses at run time. The certificates have a long validity because |
| * OCSP_check_validity() compares against the wall clock and cannot be pinned |
| * via X509_VERIFY_PARAM_set_time(). |
| * |
| * The arrays below are generated by the test-tools ocsptest command. |
| */ |
| |
| static const char *kOcspTestRoot[] = { |
| "-----BEGIN CERTIFICATE-----\n", |
| "MIID+DCCAuCgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBmjELMAkGA1UEBhMCVVMx\n", |
| "EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFTAT\n", |
| "BgNVBAoMDEV4YW1wbGUgQ29ycDEeMBwGA1UECwwVQ2VydGlmaWNhdGUgQXV0aG9y\n", |
| "aXR5MScwJQYDVQQDDB5FeGFtcGxlIENvcnAgT0NTUCBUZXN0IFJvb3QgQ0EwIBcN\n", |
| "MjYwMTAxMDAwMDAwWhgPMjEyNjAxMDEwMDAwMDBaMIGaMQswCQYDVQQGEwJVUzET\n", |
| "MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEVMBMG\n", |
| "A1UECgwMRXhhbXBsZSBDb3JwMR4wHAYDVQQLDBVDZXJ0aWZpY2F0ZSBBdXRob3Jp\n", |
| "dHkxJzAlBgNVBAMMHkV4YW1wbGUgQ29ycCBPQ1NQIFRlc3QgUm9vdCBDQTCCASIw\n", |
| "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKuZRsVUiwQoVlwfXY0nVpvMQiJN\n", |
| "Su5YfrxzKJ9sMfPI2rEg9d8kW2qsfnCB0isj+SK+CkcfVu5aXcUVUnp08VuKpsI9\n", |
| "idkeC7bhXkQgBR1p1mBwChc+UUD6qEindJPhFxYur+7gCmpamSHYr8iYmjVe78l8\n", |
| "vRHVuw8KMsiGegvPsuxIYWdY4mgKSCu3o6DeK4XehXU4Ll5j0fGX5eJgbaI6g8qE\n", |
| "j71J6G8Y4Ur/WqzTp/GZueTY0wzU8k45HS5uWarGYB2PH8DfM2SRQBw5hYd2xIvS\n", |
| "jgFYzCXeIZFnHVCMeB//VaUyYGIaw+Dreh+Wb5zBPh9FyJkrOXYyMeFZUScCAwEA\n", |
| "AaNFMEMwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O\n", |
| "BBYEFGSeLzT7Ur6wrLpFYVDHmNi/TQp5MA0GCSqGSIb3DQEBCwUAA4IBAQAMMukk\n", |
| "I0VRfxY1vZngu3LdnBk5If6TbQ6lmWatT4q3BrAID3L9zG/qev6DlyruvnVqoNdU\n", |
| "WcWXnzFSDInOKM64wU2oxdosMPWuAKKLHgDdCicikJtF+N0qJgOcyD+Gv9t0kwDB\n", |
| "O094nZUgrkCafJiy5y7KtZvqOjcvfEK+oD7fXX/VURv8NMOxpuassPHnHGvHqwKu\n", |
| "7jBZMjkOoZH4hJSo5EzZxRZHz6ay7Q8e+6C6PG8CIYXpIqukjVNq9jBb2yog67mW\n", |
| "lHlfnEENCyQDSmnEXAVNpJS67jmcItoD1utnDINVzu87DY9WiLZB06Y1xSp1ie7s\n", |
| "FIfS7bZ1cxVkt5wS\n", |
| "-----END CERTIFICATE-----\n", |
| NULL |
| }; |
| |
| static const char *kOcspTestRootKey[] = { |
| "-----BEGIN RSA PRIVATE KEY-----\n", |
| "MIIEowIBAAKCAQEAq5lGxVSLBChWXB9djSdWm8xCIk1K7lh+vHMon2wx88jasSD1\n", |
| "3yRbaqx+cIHSKyP5Ir4KRx9W7lpdxRVSenTxW4qmwj2J2R4LtuFeRCAFHWnWYHAK\n", |
| "Fz5RQPqoSKd0k+EXFi6v7uAKalqZIdivyJiaNV7vyXy9EdW7DwoyyIZ6C8+y7Ehh\n", |
| "Z1jiaApIK7ejoN4rhd6FdTguXmPR8Zfl4mBtojqDyoSPvUnobxjhSv9arNOn8Zm5\n", |
| "5NjTDNTyTjkdLm5ZqsZgHY8fwN8zZJFAHDmFh3bEi9KOAVjMJd4hkWcdUIx4H/9V\n", |
| "pTJgYhrD4Ot6H5ZvnME+H0XImSs5djIx4VlRJwIDAQABAoIBAAj+6w/d47/JtuVI\n", |
| "xlMSXzRMW/cyYsg7SWxAWT5/oeAW2n1zWJBkdopmv+YkAsw81uBfDWjhwraSHtz9\n", |
| "xioh8U6MO+ZuQB4VY3soi2mPiCpyPvPP9nzLc9+v2ZydcrtsjxTxnkrWjJU7afsK\n", |
| "l1nbw3x4HU1McG5RQbzYcFsaJFHJcVdxIYkDfEgnBok1ALaQuRUGfUVYZDVk6Ztg\n", |
| "fMUh5nfNSHWu6y2i8YCphprIfu/zwadicaYLYljYqgP9J1MOPwuMcoCoWgotBUCZ\n", |
| "+29qIPn1mK3ReBmYdE8IIEiSLHYJjJ7EVu8IUfSPotBGGC5PjC11HcCXx0xB9AfB\n", |
| "I8VcDikCgYEA089WizVCWZMxWnCPLDG036vsug3/rrPr/O3W5VXTdpr00CBRzund\n", |
| "7QnaxUyxw37SOAQUtzcKhC0CF3c7Dbryb8d51koROVlWC8rngoDMxiZkbZZe0kL1\n", |
| "jHkOHEOoi83uY0tFoRhYtrcOYObNT9JDifdIDYCnxbLW4UQLo/9mFmUCgYEAz2ZH\n", |
| "hxoxXJ9y3qmIcc2vZTRPdaB4r+qQi5krUgtYg1uKImrvDnnl/4xCnCG9G1s1M/wE\n", |
| "cvuFG5FWGz6TtS0TsCGUXVWZ9s67JT53l02RIVTog/VRHbKsOnj+d9oXglGcxALT\n", |
| "qG02lKocNHzrPUXEw/EIMETKR6WvATZCzhM9mpsCgYB9RoKfb27A4Cgun6husS+T\n", |
| "o3IuUR1KzSvkux+BIRQjcF8fwh3gzb3u9wcn7satJBNeAjvmaW2U47H7AxAwfMPr\n", |
| "jQXo0oIBc29LJkVrkJaNFCQOFQQcRHJLFUZdPT8xASngHKMgNvAxkW+1rIz+ixRb\n", |
| "Q6CgK9oPOkmRjtd7thFBaQKBgQCMbt0QBhRWe0D0tCbHqFaTWJBVPYt60oF9hQFo\n", |
| "VHZiu6EVHQMx8ihimT6hKdc6ps+nm4YHtXez6v07BWxOyW8DXDlx2XyfOexOk7W2\n", |
| "pbcXsr6eW4XJbipgjX0A+pPgkhJsRt26tfi3QVhH0i4XFx7c7mB1Dp9JVE7jqzIh\n", |
| "B7Y28QKBgCg93v7zP5GFmOa6zCZreIIfi1dy50otxfqYewcXy4Egt90cE67vY55u\n", |
| "3B44ySrLkKDuzX2Inrwp5Vao8b9pDQ/AisRzt617eO1H5JtRF3lzZJukYC6j4urU\n", |
| "24kB2IhZCB6/3pwGiS21ma9E6OF9tO5YaGGYo02ZqkoflN+XgoeZ\n", |
| "-----END RSA PRIVATE KEY-----\n", |
| NULL |
| }; |
| |
| static const char *kOcspTestLeaf[] = { |
| "-----BEGIN CERTIFICATE-----\n", |
| "MIIEOzCCAyOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZoxCzAJBgNVBAYTAlVT\n", |
| "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUw\n", |
| "EwYDVQQKDAxFeGFtcGxlIENvcnAxHjAcBgNVBAsMFUNlcnRpZmljYXRlIEF1dGhv\n", |
| "cml0eTEnMCUGA1UEAwweRXhhbXBsZSBDb3JwIE9DU1AgVGVzdCBSb290IENBMCAX\n", |
| "DTI2MDEwMTAwMDAwMFoYDzIxMjYwMTAxMDAwMDAwWjCBiDELMAkGA1UEBhMCVVMx\n", |
| "EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFTAT\n", |
| "BgNVBAoMDEV4YW1wbGUgQ29ycDEVMBMGA1UECwwMV2ViIFNlcnZpY2VzMR4wHAYD\n", |
| "VQQDDBVvY3NwLWxlYWYuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB\n", |
| "DwAwggEKAoIBAQCoQbsBGnLjATBzU8eWYMeyzu6vy4scpVDdhGnTWMaSIrqoXXge\n", |
| "JXrMHavT13cv2wNTExA6BNqFZA6YLBXYpDJ5oXyOlY1SYjbapX4M0kry4tBZdGWu\n", |
| "vnh04Q07SI8JvjtScB3lAIIhGr1WrQNLfEz+O80j4Pp8kLe1fWi0joB1CG4RWiuH\n", |
| "/2Ls1rSEMTr6dABtQ+zwxRHcFlEAoR9ZEDzfN1hIQEByWJd7TMnv738usyp52wMi\n", |
| "Gh/sruYHkpsO2tVoLCwm1OMSR1BLdGO1tJWSYN2+Tj2JVleQWcwwCgzDX4OlIdPF\n", |
| "/CM/6aQA6BkDeMW//tO4Ec4X+530zPiFKcZLAgMBAAGjgZgwgZUwDAYDVR0TAQH/\n", |
| "BAIwADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0O\n", |
| "BBYEFBEZYONIpHIGBtlfPSlUTcDccGMiMB8GA1UdIwQYMBaAFGSeLzT7Ur6wrLpF\n", |
| "YVDHmNi/TQp5MCAGA1UdEQQZMBeCFW9jc3AtbGVhZi5leGFtcGxlLmNvbTANBgkq\n", |
| "hkiG9w0BAQsFAAOCAQEAaFYoQjmWdBBiD/hfSgV34Jf+PVKkecuu60VKDasPLNyV\n", |
| "ZwZcW8dXF9NOYcebGIEx4rjQTC3xiHUknqfOzc2jmPdU/xBAyRiltQnUh3OFH1qn\n", |
| "bX0YNUgfluLW+YSwNkriFLuzESBVadGhlX94mQwoqYyQJ+6/Ht2j4P4ZiIDRWfgc\n", |
| "z9pN8YoCiXh/I/IxVIWunk7Dla+Gr6BDJ762iQMMzPQ5D3cRAe9BDRgGiN0lPeIa\n", |
| "LMtqDeZZ+dR0KZAr3yZcfyci8SNXwCBbjsoVjmuUj6dlN12pRKxxtBSa23KT6/Dy\n", |
| "ijXZ+PtyIJz8FVBxO0RoECLimwbUPHfNjAWjuJkugA==\n", |
| "-----END CERTIFICATE-----\n", |
| NULL |
| }; |
| |
| /* Load the fixed PKI. Any of the out params may be NULL to skip it. */ |
| static int load_pki(X509 **root, EVP_PKEY **root_key, X509 **leaf) |
| { |
| if (root != NULL && !TEST_ptr(*root = X509_from_strings(kOcspTestRoot))) |
| return 0; |
| if (root_key != NULL |
| && !TEST_ptr(*root_key = PKEY_from_strings(kOcspTestRootKey))) |
| return 0; |
| if (leaf != NULL && !TEST_ptr(*leaf = X509_from_strings(kOcspTestLeaf))) |
| return 0; |
| return 1; |
| } |
| |
| /* |
| * Build a signed OCSP response for |cert| (issued by |issuer|). |resp_status| |
| * is the outer response status, |cert_status| the single-response certificate |
| * status. thisUpdate and nextUpdate are the current time offset by |
| * |this_off_sec| and |next_off_sec| seconds, so callers can also produce |
| * expired or not-yet-valid responses. The response is signed by |
| * |signer|/|signer_key|. Returns a response the caller must free, or NULL. |
| */ |
| static OCSP_RESPONSE *make_ocsp_response(X509 *cert, X509 *issuer, |
| int resp_status, int cert_status, int this_off_sec, int next_off_sec, |
| X509 *signer, EVP_PKEY *signer_key) |
| { |
| OCSP_RESPONSE *resp = NULL; |
| OCSP_BASICRESP *bs = NULL; |
| OCSP_CERTID *cid = NULL; |
| ASN1_TIME *thisupd = NULL, *nextupd = NULL, *revtime = NULL; |
| |
| if (cert_status == V_OCSP_CERTSTATUS_REVOKED |
| && !TEST_ptr(revtime = X509_gmtime_adj(NULL, 0))) |
| goto end; |
| |
| if (!TEST_ptr(bs = OCSP_BASICRESP_new()) |
| || !TEST_ptr(thisupd = X509_time_adj_ex(NULL, 0, this_off_sec, NULL)) |
| || !TEST_ptr(nextupd = X509_time_adj_ex(NULL, 0, next_off_sec, NULL)) |
| || !TEST_ptr(cid = OCSP_cert_to_id(EVP_sha256(), cert, issuer)) |
| || !TEST_ptr(OCSP_basic_add1_status(bs, cid, cert_status, 0, revtime, |
| thisupd, nextupd)) |
| || !TEST_true(OCSP_basic_sign(bs, signer, signer_key, EVP_sha256(), |
| NULL, OCSP_NOCERTS))) |
| goto end; |
| |
| resp = OCSP_response_create(resp_status, bs); |
| |
| end: |
| ASN1_TIME_free(revtime); |
| ASN1_TIME_free(thisupd); |
| ASN1_TIME_free(nextupd); |
| OCSP_CERTID_free(cid); |
| OCSP_BASICRESP_free(bs); |
| return resp; |
| } |
| |
| /* Wrap |resp| into a stack, taking ownership on success. */ |
| static STACK_OF(OCSP_RESPONSE) *make_ocsp_resp_stack(OCSP_RESPONSE *resp) |
| { |
| STACK_OF(OCSP_RESPONSE) *sk = sk_OCSP_RESPONSE_new_null(); |
| |
| if (!TEST_ptr(sk)) |
| return NULL; |
| if (!TEST_true(sk_OCSP_RESPONSE_push(sk, resp))) { |
| sk_OCSP_RESPONSE_free(sk); |
| return NULL; |
| } |
| return sk; |
| } |
| |
| /* |
| * Verify |leaf| against |root| with the stapled |resps| and |flags|, taking |
| * ownership of |resps|. Returns X509_V_OK or an X509_V_ERR_xxx code. The |
| * X509_verify_cert() call is wrapped for malloc-failure injection. |
| */ |
| static int verify_ocsp(X509 *leaf, X509 *root, STACK_OF(OCSP_RESPONSE) *resps, |
| unsigned long flags) |
| { |
| X509_STORE *store = X509_STORE_new(); |
| X509_STORE_CTX *ctx = X509_STORE_CTX_new(); |
| X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); |
| int status = X509_V_ERR_UNSPECIFIED; |
| |
| if (!TEST_ptr(store) || !TEST_ptr(ctx) || !TEST_ptr(param)) |
| goto end; |
| |
| if (!TEST_true(X509_STORE_add_cert(store, root)) |
| || !TEST_true(X509_STORE_CTX_init(ctx, store, leaf, NULL))) |
| goto end; |
| |
| X509_STORE_CTX_set_ocsp_resp(ctx, resps); |
| |
| X509_VERIFY_PARAM_set_depth(param, 16); |
| if (flags != 0) |
| X509_VERIFY_PARAM_set_flags(param, flags); |
| X509_STORE_CTX_set0_param(ctx, param); |
| param = NULL; |
| |
| ERR_clear_error(); |
| MFAIL_start(); |
| status = X509_verify_cert(ctx) == 1 ? X509_V_OK |
| : X509_STORE_CTX_get_error(ctx); |
| MFAIL_end(); |
| |
| end: |
| X509_VERIFY_PARAM_free(param); |
| X509_STORE_CTX_free(ctx); |
| X509_STORE_free(store); |
| sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); |
| return status; |
| } |
| |
| /* |
| * Build a single response for the leaf and verify it, expecting |expected|. |
| * Every failure inside check_cert_ocsp_resp() surfaces as |
| * X509_V_ERR_OCSP_VERIFY_FAILED at the X509_verify_cert() level. |
| */ |
| static int run_ocsp_verify(int resp_status, int cert_status, int this_off_sec, |
| int next_off_sec, int expected) |
| { |
| X509 *root = NULL, *leaf = NULL; |
| EVP_PKEY *root_key = NULL; |
| OCSP_RESPONSE *resp = NULL; |
| STACK_OF(OCSP_RESPONSE) *resps = NULL; |
| int testresult = 0; |
| |
| if (!load_pki(&root, &root_key, &leaf)) |
| goto end; |
| |
| if (!TEST_ptr(resp = make_ocsp_response(leaf, root, resp_status, cert_status, |
| this_off_sec, next_off_sec, root, root_key)) |
| || !TEST_ptr(resps = make_ocsp_resp_stack(resp))) |
| goto end; |
| resp = NULL; /* owned by resps */ |
| |
| testresult = TEST_int_eq(verify_ocsp(leaf, root, resps, |
| X509_V_FLAG_OCSP_RESP_CHECK), |
| expected); |
| resps = NULL; /* freed by verify_ocsp */ |
| |
| end: |
| sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); |
| OCSP_RESPONSE_free(resp); |
| EVP_PKEY_free(root_key); |
| X509_free(leaf); |
| X509_free(root); |
| return testresult; |
| } |
| |
| /* |
| * A good response that expired a moment ago is still accepted, because stapled |
| * responses are honoured for up to five minutes past nextUpdate. |
| */ |
| static int test_ocsp_resp_good(void) |
| { |
| return run_ocsp_verify(OCSP_RESPONSE_STATUS_SUCCESSFUL, |
| V_OCSP_CERTSTATUS_GOOD, -10 * 60, -2 * 60, X509_V_OK); |
| } |
| |
| /* An outer response status other than successful is rejected. */ |
| static int test_ocsp_resp_not_successful(void) |
| { |
| return run_ocsp_verify(OCSP_RESPONSE_STATUS_TRYLATER, |
| V_OCSP_CERTSTATUS_GOOD, 0, 24 * 60 * 60, X509_V_ERR_OCSP_VERIFY_FAILED); |
| } |
| |
| /* A response more than five minutes past nextUpdate is rejected as expired. */ |
| static int test_ocsp_resp_expired(void) |
| { |
| return run_ocsp_verify(OCSP_RESPONSE_STATUS_SUCCESSFUL, |
| V_OCSP_CERTSTATUS_GOOD, -20 * 60, -10 * 60, X509_V_ERR_OCSP_VERIFY_FAILED); |
| } |
| |
| /* No response for the leaf's depth: sk_OCSP_RESPONSE_num() <= error_depth. */ |
| static int test_ocsp_resp_none(void) |
| { |
| X509 *root = NULL, *leaf = NULL; |
| STACK_OF(OCSP_RESPONSE) *resps = NULL; |
| int testresult = 0; |
| |
| if (!load_pki(&root, NULL, &leaf) |
| || !TEST_ptr(resps = sk_OCSP_RESPONSE_new_null())) |
| goto end; |
| |
| testresult = TEST_int_eq(verify_ocsp(leaf, root, resps, |
| X509_V_FLAG_OCSP_RESP_CHECK), |
| X509_V_ERR_OCSP_VERIFY_FAILED); |
| resps = NULL; /* freed by verify_ocsp */ |
| |
| end: |
| sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); |
| X509_free(leaf); |
| X509_free(root); |
| return testresult; |
| } |
| |
| /* |
| * A well-formed response carrying a single response for a different certificate: |
| * no CertID matches the leaf, so no status is found for it. |
| */ |
| static int test_ocsp_resp_wrong_cert(void) |
| { |
| X509 *root = NULL, *leaf = NULL; |
| EVP_PKEY *root_key = NULL; |
| OCSP_RESPONSE *resp = NULL; |
| STACK_OF(OCSP_RESPONSE) *resps = NULL; |
| int testresult = 0; |
| |
| if (!load_pki(&root, &root_key, &leaf)) |
| goto end; |
| |
| /* the response is about the root, not the leaf being verified */ |
| if (!TEST_ptr(resp = make_ocsp_response(root, root, |
| OCSP_RESPONSE_STATUS_SUCCESSFUL, V_OCSP_CERTSTATUS_GOOD, 0, |
| 24 * 60 * 60, root, root_key)) |
| || !TEST_ptr(resps = make_ocsp_resp_stack(resp))) |
| goto end; |
| resp = NULL; /* owned by resps */ |
| |
| testresult = TEST_int_eq(verify_ocsp(leaf, root, resps, |
| X509_V_FLAG_OCSP_RESP_CHECK), |
| X509_V_ERR_OCSP_VERIFY_FAILED); |
| resps = NULL; /* freed by verify_ocsp */ |
| |
| end: |
| sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); |
| OCSP_RESPONSE_free(resp); |
| EVP_PKEY_free(root_key); |
| X509_free(leaf); |
| X509_free(root); |
| return testresult; |
| } |
| |
| /* Exercise the success path under mfail. */ |
| static int test_ocsp_resp_mfail(void) |
| { |
| X509 *root = NULL, *leaf = NULL; |
| EVP_PKEY *root_key = NULL; |
| OCSP_RESPONSE *resp = NULL; |
| STACK_OF(OCSP_RESPONSE) *resps = NULL; |
| int testresult = 0; |
| |
| if (!load_pki(&root, &root_key, &leaf)) |
| goto end; |
| |
| if (!TEST_ptr(resp = make_ocsp_response(leaf, root, |
| OCSP_RESPONSE_STATUS_SUCCESSFUL, V_OCSP_CERTSTATUS_GOOD, 0, |
| 24 * 60 * 60, root, root_key)) |
| || !TEST_ptr(resps = make_ocsp_resp_stack(resp))) |
| goto end; |
| resp = NULL; /* owned by resps */ |
| |
| testresult = verify_ocsp(leaf, root, resps, X509_V_FLAG_OCSP_RESP_CHECK) |
| == X509_V_OK; |
| resps = NULL; /* freed by verify_ocsp */ |
| |
| end: |
| sk_OCSP_RESPONSE_pop_free(resps, OCSP_RESPONSE_free); |
| OCSP_RESPONSE_free(resp); |
| EVP_PKEY_free(root_key); |
| X509_free(leaf); |
| X509_free(root); |
| return testresult; |
| } |
| |
| #endif /* OPENSSL_NO_OCSP */ |
| |
| int setup_tests(void) |
| { |
| #ifndef OPENSSL_NO_OCSP |
| ADD_TEST(test_ocsp_resp_good); |
| ADD_TEST(test_ocsp_resp_not_successful); |
| ADD_TEST(test_ocsp_resp_expired); |
| ADD_TEST(test_ocsp_resp_none); |
| ADD_TEST(test_ocsp_resp_wrong_cert); |
| ADD_MFAIL_NO_CHECK_TEST(test_ocsp_resp_mfail); |
| #endif |
| return 1; |
| } |