diff --git a/crypto/ocsp/ocsp_server.c b/crypto/ocsp/ocsp_server.c index 02c33ca415..dd10c2ee43 100644 --- a/crypto/ocsp/ocsp_server.c +++ b/crypto/ocsp/ocsp_server.c @@ -70,3 +70,125 @@ int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert) { X509_up_ref(cert); return 1; } + +static int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert) { + GUARD_PTR(respid); + GUARD_PTR(cert); + if (!X509_NAME_set(&respid->value.byName, X509_get_subject_name(cert))) { + return 0; + } + + respid->type = V_OCSP_RESPID_NAME; + return 1; +} + +static int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert) { + GUARD_PTR(respid); + GUARD_PTR(cert); + + // RFC2560 requires SHA1. + unsigned char digest[SHA_DIGEST_LENGTH]; + if (!X509_pubkey_digest(cert, EVP_sha1(), digest, NULL)) { + return 0; + } + + ASN1_OCTET_STRING *byKey = ASN1_OCTET_STRING_new(); + if (byKey == NULL) { + return 0; + } + + if (!ASN1_OCTET_STRING_set(byKey, digest, SHA_DIGEST_LENGTH)) { + ASN1_OCTET_STRING_free(byKey); + return 0; + } + respid->type = V_OCSP_RESPID_KEY; + respid->value.byKey = byKey; + + return 1; +} + + +// OCSP_basic_sign_ctx does the actual signing operation for |OCSP_basic_sign|, +// but with an initialized |EVP_MD_CTX|. +static int OCSP_basic_sign_ctx(OCSP_BASICRESP *resp, X509 *signer, + EVP_MD_CTX *ctx, STACK_OF(X509) *certs, + unsigned long flags) { + GUARD_PTR(resp); + GUARD_PTR(signer); + + if (ctx == NULL || ctx->pctx == NULL) { + OPENSSL_PUT_ERROR(OCSP, OCSP_R_NO_SIGNER_KEY); + return 0; + } + + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + if (pkey == NULL || !X509_check_private_key(signer, pkey)) { + OPENSSL_PUT_ERROR(OCSP, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return 0; + } + + // Add relevant certificates to the response. This is optional according to + // the RFC. + if (!IS_OCSP_FLAG_SET(flags, OCSP_NOCERTS)) { + if (!OCSP_basic_add1_cert(resp, signer)) { + return 0; + } + for (size_t i = 0; i < sk_X509_num(certs); i++) { + X509 *tmpcert = sk_X509_value(certs, i); + if (!OCSP_basic_add1_cert(resp, tmpcert)) { + return 0; + } + } + } + + // Set |responderId| of response. + OCSP_RESPID *rid = resp->tbsResponseData->responderId; + if (IS_OCSP_FLAG_SET(flags, OCSP_RESPID_KEY)) { + if (!OCSP_RESPID_set_by_key(rid, signer)) { + return 0; + } + } else if (!OCSP_RESPID_set_by_name(rid, signer)) { + // The OCSP responder is identified by name by default. + return 0; + } + + // Set |producedAt| time field of response. Although this can be + // excluded with |OCSP_NOTIME|, a definitive response should include + // the generation time. + if (!IS_OCSP_FLAG_SET(flags, OCSP_NOTIME)) { + if (!X509_gmtime_adj(resp->tbsResponseData->producedAt, 0)) { + return 0; + } + } + + // Do the actual signing. This is mandatory according to the RFC. + if (!ASN1_item_sign_ctx(ASN1_ITEM_rptr(OCSP_RESPDATA), + resp->signatureAlgorithm, NULL, resp->signature, + resp->tbsResponseData, ctx)) { + return 0; + } + + return 1; +} + +int OCSP_basic_sign(OCSP_BASICRESP *resp, X509 *signer, EVP_PKEY *key, + const EVP_MD *dgst, STACK_OF(X509) *certs, + unsigned long flags) { + GUARD_PTR(resp); + GUARD_PTR(signer); + GUARD_PTR(key); + GUARD_PTR(dgst); + + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + return 0; + } + + if (!EVP_DigestSignInit(ctx, NULL, dgst, NULL, key)) { + EVP_MD_CTX_free(ctx); + return 0; + } + int ret = OCSP_basic_sign_ctx(resp, signer, ctx, certs, flags); + EVP_MD_CTX_free(ctx); + return ret; +} diff --git a/crypto/ocsp/ocsp_test.cc b/crypto/ocsp/ocsp_test.cc index 859f9a5794..8a4143aa9f 100644 --- a/crypto/ocsp/ocsp_test.cc +++ b/crypto/ocsp/ocsp_test.cc @@ -35,8 +35,8 @@ static const time_t invalid_after_ocsp_expire_time_sha256 = 1937505764; #define OCSP_HTTP_PARSE_SUCCESS 1 #define OCSP_HTTP_PARSE_ERROR 0 -#define OCSP_REQUEST_SIGN_SUCCESS 1 -#define OCSP_REQUEST_SIGN_ERROR 0 +#define OCSP_SIGN_SUCCESS 1 +#define OCSP_SIGN_ERROR 0 #define OCSP_URL_PARSE_SUCCESS 1 #define OCSP_URL_PARSE_ERROR 0 @@ -134,7 +134,6 @@ static void ExtractAndVerifyBasicOCSP( bssl::UniquePtr *basic_response, bssl::UniquePtr *server_cert_chain) { bssl::UniquePtr ocsp_response; - ocsp_response = LoadOCSP_RESPONSE(der); ASSERT_TRUE(ocsp_response); @@ -282,7 +281,7 @@ class OCSPTestAWS : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P(All, OCSPTestAWS, testing::ValuesIn(nTestVectors)); -TEST_P(OCSPTestAWS, VerifyOCSPResponseExtended) { +TEST_P(OCSPTestAWS, VerifyOCSPResponse) { const OCSPAWSTestVector &t = GetParam(); std::string data = @@ -348,7 +347,7 @@ class OCSPResponseStatusTest INSTANTIATE_TEST_SUITE_P(All, OCSPResponseStatusTest, testing::ValuesIn(respTestVectors)); -TEST_P(OCSPResponseStatusTest, VerifyOCSPResponseExtended) { +TEST_P(OCSPResponseStatusTest, OCSPResponseStatus) { const OCSPResponseStatusTestVector &t = GetParam(); std::string data = @@ -792,7 +791,7 @@ TEST_P(OCSPTest, VerifyOCSPResponse) { ASSERT_EQ(t.expected_ocsp_verify_status, ocsp_verify_status); } -struct OCSPReqTestVector { +struct OCSPRequestTestVector { const char *ocsp_request; int expected_parse_status; int expected_sign_status; @@ -801,42 +800,41 @@ struct OCSPReqTestVector { const EVP_MD *dgst; }; -static const OCSPReqTestVector kRequestTestVectors[] = { - {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_SUCCESS, +static const OCSPRequestTestVector kRequestTestVectors[] = { + {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_SUCCESS, "server_cert", "server_key", EVP_sha1()}, - {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_SUCCESS, + {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_SUCCESS, "server_cert", "server_key", EVP_sha256()}, - {"ocsp_request_attached_cert", OCSP_REQUEST_PARSE_SUCCESS, - OCSP_REQUEST_SIGN_ERROR, "server_cert", "server_key", nullptr}, - {"ocsp_request_no_nonce", OCSP_REQUEST_PARSE_SUCCESS, - OCSP_REQUEST_SIGN_SUCCESS, "server_cert", "server_key", EVP_sha512()}, - {"ocsp_request_signed", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_ERROR, + {"ocsp_request_attached_cert", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_ERROR, + "server_cert", "server_key", nullptr}, + {"ocsp_request_no_nonce", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_SUCCESS, + "server_cert", "server_key", EVP_sha512()}, + {"ocsp_request_signed", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_ERROR, "server_cert", "server_key", nullptr}, - {"ocsp_request_signed_sha256", OCSP_REQUEST_PARSE_SUCCESS, - OCSP_REQUEST_SIGN_ERROR, "server_cert", "server_key", nullptr}, - {"ocsp_response", OCSP_REQUEST_PARSE_ERROR, OCSP_REQUEST_SIGN_ERROR, + {"ocsp_request_signed_sha256", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_ERROR, "server_cert", "server_key", nullptr}, + {"ocsp_response", OCSP_REQUEST_PARSE_ERROR, OCSP_SIGN_ERROR, "server_cert", + "server_key", nullptr}, // Test signing with ECDSA certs and keys. - {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_SUCCESS, + {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_SUCCESS, "server_ecdsa_cert", "server_ecdsa_key", EVP_sha1()}, - {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_SUCCESS, + {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_SUCCESS, + "server_ecdsa_cert", "server_ecdsa_key", EVP_sha256()}, + {"ocsp_request_no_nonce", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_SUCCESS, + "server_cert", "server_key", EVP_sha256()}, + {"ocsp_request_no_nonce", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_SUCCESS, "server_ecdsa_cert", "server_ecdsa_key", EVP_sha256()}, - {"ocsp_request_no_nonce", OCSP_REQUEST_PARSE_SUCCESS, - OCSP_REQUEST_SIGN_SUCCESS, "server_cert", "server_key", EVP_sha256()}, - {"ocsp_request_no_nonce", OCSP_REQUEST_PARSE_SUCCESS, - OCSP_REQUEST_SIGN_SUCCESS, "server_ecdsa_cert", "server_ecdsa_key", - EVP_sha256()}, // Test certificate type mismatch. - {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_ERROR, - "server_cert", "server_ecdsa_key", EVP_sha256()}, - {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_ERROR, + {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_ERROR, "server_cert", + "server_ecdsa_key", EVP_sha256()}, + {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_ERROR, "server_ecdsa_cert", "server_key", EVP_sha256()}, // Test certificate key and cert mismatch. - {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_REQUEST_SIGN_ERROR, - "ca_cert", "server_key", EVP_sha256()}, + {"ocsp_request", OCSP_REQUEST_PARSE_SUCCESS, OCSP_SIGN_ERROR, "ca_cert", + "server_key", EVP_sha256()}, }; -class OCSPRequestTest : public testing::TestWithParam {}; +class OCSPRequestTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P(All, OCSPRequestTest, testing::ValuesIn(kRequestTestVectors)); @@ -847,7 +845,7 @@ static const char good_http_request_hdr[] = "Content-Length: "; TEST_P(OCSPRequestTest, OCSPRequestParse) { - const OCSPReqTestVector &t = GetParam(); + const OCSPRequestTestVector &t = GetParam(); std::string data = GetTestData(std::string("crypto/ocsp/test/aws/" + @@ -901,7 +899,7 @@ TEST_P(OCSPRequestTest, OCSPRequestParse) { } TEST_P(OCSPRequestTest, OCSPRequestSign) { - const OCSPReqTestVector &t = GetParam(); + const OCSPRequestTestVector &t = GetParam(); std::string data = GetTestData(std::string("crypto/ocsp/test/aws/" + @@ -944,7 +942,7 @@ TEST_P(OCSPRequestTest, OCSPRequestSign) { int ret = OCSP_request_sign(ocspRequest.get(), server_cert.get(), pkey.get(), t.dgst, additional_cert.get(), 0); - if (t.expected_sign_status == OCSP_REQUEST_SIGN_SUCCESS) { + if (t.expected_sign_status == OCSP_SIGN_SUCCESS) { ASSERT_TRUE(ret); EXPECT_TRUE(OCSP_request_is_signed(ocspRequest.get())); } else { @@ -954,6 +952,168 @@ TEST_P(OCSPRequestTest, OCSPRequestSign) { } } +struct OCSPResponseSignTestVector { + int expected_sign_status; + const char *signer_cert; + const char *private_key; + const EVP_MD *dgst; +}; + +static const OCSPResponseSignTestVector kOCSPResponseSignTestVectors[] = { + {OCSP_SIGN_SUCCESS, "server_cert", "server_key", EVP_sha1()}, + {OCSP_SIGN_SUCCESS, "server_cert", "server_key", EVP_sha256()}, + {OCSP_SIGN_SUCCESS, "server_cert", "server_key", EVP_sha512()}, + // Test signing with ECDSA certs and keys. + {OCSP_SIGN_SUCCESS, "server_ecdsa_cert", "server_ecdsa_key", EVP_sha1()}, + {OCSP_SIGN_SUCCESS, "server_ecdsa_cert", "server_ecdsa_key", EVP_sha256()}, + {OCSP_SIGN_SUCCESS, "server_ecdsa_cert", "server_ecdsa_key", EVP_sha512()}, + // Test certificate type mismatch. + {OCSP_SIGN_ERROR, "server_cert", "server_ecdsa_key", EVP_sha256()}, + {OCSP_SIGN_ERROR, "server_ecdsa_cert", "server_key", EVP_sha256()}, + // Test certificate key and cert mismatch. + {OCSP_SIGN_ERROR, "ca_cert", "server_key", EVP_sha256()}, +}; + +class OCSPResponseSignTest + : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(All, OCSPResponseSignTest, + testing::ValuesIn(kOCSPResponseSignTestVectors)); + +TEST_P(OCSPResponseSignTest, OCSPResponseSign) { + const OCSPResponseSignTestVector &t = GetParam(); + + // Set up an empty |OCSP_BASICRESP| for signing. + bssl::UniquePtr basic_response(OCSP_BASICRESP_new()); + ASSERT_TRUE(basic_response); + + // Gather certs and key needed for signing. + bssl::UniquePtr signer_cert( + CertFromPEM(GetTestData(std::string("crypto/ocsp/test/aws/" + + std::string(t.signer_cert) + ".pem") + .c_str()) + .c_str())); + ASSERT_TRUE(signer_cert); + bssl::UniquePtr ca_cert(CertFromPEM( + GetTestData(std::string("crypto/ocsp/test/aws/ca_cert.pem").c_str()) + .c_str())); + ASSERT_TRUE(ca_cert); + bssl::UniquePtr pkey(EVP_PKEY_new()); + if (std::string(t.private_key) == "server_key") { + bssl::UniquePtr rsa( + RSAFromPEM(GetTestData(std::string("crypto/ocsp/test/aws/" + + std::string(t.private_key) + ".pem") + .c_str()) + .c_str())); + ASSERT_TRUE(rsa); + ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey.get(), rsa.get())); + } else { + bssl::UniquePtr ecdsa(ECDSAFromPEM( + GetTestData(std::string("crypto/ocsp/test/aws/" + + std::string(t.private_key) + ".pem") + .c_str()) + .c_str())); + ASSERT_TRUE(ecdsa); + ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(pkey.get(), ecdsa.get())); + } + + // Do the actual sign. + EXPECT_EQ(OCSP_basic_sign(basic_response.get(), signer_cert.get(), pkey.get(), + t.dgst, CertsToStack({ca_cert.get()}).get(), 0), + t.expected_sign_status); + if (t.expected_sign_status == OCSP_SIGN_SUCCESS) { + bssl::UniquePtr trust_store(X509_STORE_new()); + ASSERT_TRUE(X509_STORE_add_cert(trust_store.get(), ca_cert.get())); + EXPECT_TRUE(OCSP_basic_verify(basic_response.get(), + CertsToStack({signer_cert.get()}).get(), + trust_store.get(), 0)); + } +} + +// Test against various flags for |OCSP_basic_sign|. +TEST(OCSPResponseSignTestExtended, OCSPResponseSign) { + bssl::UniquePtr basic_response(OCSP_BASICRESP_new()); + ASSERT_TRUE(basic_response); + + bssl::UniquePtr signer_cert(CertFromPEM( + GetTestData(std::string("crypto/ocsp/test/aws/server_cert.pem").c_str()) + .c_str())); + ASSERT_TRUE(signer_cert); + bssl::UniquePtr ca_cert(CertFromPEM( + GetTestData(std::string("crypto/ocsp/test/aws/ca_cert.pem").c_str()) + .c_str())); + ASSERT_TRUE(ca_cert); + bssl::UniquePtr additional_cert = + CertsToStack({ca_cert.get()}); + + bssl::UniquePtr pkey(EVP_PKEY_new()); + bssl::UniquePtr rsa(RSAFromPEM( + GetTestData(std::string("crypto/ocsp/test/aws/server_key.pem").c_str()) + .c_str())); + ASSERT_TRUE(rsa); + ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey.get(), rsa.get())); + + // Call |OCSP_basic_sign| with no flags and check the expected output. + EXPECT_TRUE(OCSP_basic_sign(basic_response.get(), signer_cert.get(), + pkey.get(), EVP_sha256(), additional_cert.get(), + 0)); + EXPECT_TRUE( + ASN1_TIME_check(basic_response.get()->tbsResponseData->producedAt)); + // Allow for time field to be within two hours. + EXPECT_GT( + X509_cmp_time_posix(basic_response.get()->tbsResponseData->producedAt, + time(nullptr) - 3600), + 0); + EXPECT_LT( + X509_cmp_time_posix(basic_response.get()->tbsResponseData->producedAt, + time(nullptr) + 3600), + 0); + + EXPECT_EQ(basic_response.get()->tbsResponseData->responderId->type, + V_OCSP_RESPID_NAME); + EXPECT_EQ( + X509_NAME_cmp( + basic_response.get()->tbsResponseData->responderId->value.byName, + X509_get_subject_name(signer_cert.get())), + 0); + EXPECT_EQ((int)sk_X509_num(basic_response.get()->certs), 2); + EXPECT_EQ(X509_cmp(sk_X509_value(basic_response.get()->certs, 0), + signer_cert.get()), + 0); + EXPECT_EQ(X509_cmp(sk_X509_value(basic_response.get()->certs, 1), + sk_X509_value(additional_cert.get(), 0)), + 0); + + // Check expected effects of |OCSP_NOTIME|. + basic_response.reset(OCSP_BASICRESP_new()); + ASSERT_TRUE(basic_response); + EXPECT_TRUE(OCSP_basic_sign(basic_response.get(), signer_cert.get(), + pkey.get(), EVP_sha256(), additional_cert.get(), + OCSP_NOTIME)); + EXPECT_FALSE( + ASN1_TIME_check(basic_response.get()->tbsResponseData->producedAt)); + + // Check expected effects of |OCSP_RESPID_KEY|. + basic_response.reset(OCSP_BASICRESP_new()); + ASSERT_TRUE(basic_response); + ASSERT_FALSE(basic_response.get()->tbsResponseData->responderId->value.byKey); + EXPECT_TRUE(OCSP_basic_sign(basic_response.get(), signer_cert.get(), + pkey.get(), EVP_sha256(), additional_cert.get(), + OCSP_RESPID_KEY)); + EXPECT_EQ(basic_response.get()->tbsResponseData->responderId->type, + V_OCSP_RESPID_KEY); + EXPECT_TRUE(basic_response.get()->tbsResponseData->responderId->value.byKey); + + + // Check expected effects of |OCSP_NOCERTS|. + basic_response.reset(OCSP_BASICRESP_new()); + ASSERT_TRUE(basic_response); + EXPECT_TRUE(OCSP_basic_sign(basic_response.get(), signer_cert.get(), + pkey.get(), EVP_sha256(), additional_cert.get(), + OCSP_NOCERTS)); + EXPECT_EQ((int)sk_X509_num(basic_response.get()->certs), 0); +} + static const char extended_good_http_request_hdr[] = "POST / HTTP/1.0\r\n" "Accept-Charset: character-set\r\n" diff --git a/include/openssl/ocsp.h b/include/openssl/ocsp.h index df1f4b8fc7..7e9a4d9c42 100644 --- a/include/openssl/ocsp.h +++ b/include/openssl/ocsp.h @@ -22,8 +22,9 @@ extern "C" { // Various OCSP flags and values -// OCSP_NOCERTS is for |OCSP_request_sign| if no certificates are included -// in the |OCSP_REQUEST|. Certificates are optional. +// OCSP_NOCERTS is for |OCSP_request_sign| and |OCSP_basic_sign|. Setting +// this excludes certificates request/response and ignores the |certs| +// parameter. Certificates are optional. #define OCSP_NOCERTS 0x1 // OCSP_NOINTERN is for |OCSP_basic_verify|. Certificates included within |bs| // by the responder will be searched for the signer certificate, unless the @@ -46,6 +47,15 @@ extern "C" { // response signer's cert is one of those in the |certs| stack then it is // implicitly trusted. #define OCSP_TRUSTOTHER 0x200 +// OCSP_RESPID_KEY is for |OCSP_basic_sign|. By default, the OCSP responder is +// identified by name and included in the response. Setting this changes the +// default identifier to be the hash of the issuer's public key instead. +#define OCSP_RESPID_KEY 0x400 +// OCSP_NOTIME is for |OCSP_basic_sign|. Setting this excludes the default +// behavior of setting the |producedAt| time field in |resp| against the current +// time and leaves it empty. +#define OCSP_NOTIME 0x800 + typedef struct ocsp_cert_id_st OCSP_CERTID; typedef struct ocsp_one_request_st OCSP_ONEREQ; @@ -226,10 +236,16 @@ OPENSSL_EXPORT int OCSP_request_onereq_count(OCSP_REQUEST *req); // NULL if |i| is out of bounds. OPENSSL_EXPORT OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i); -// OCSP_request_sign signs an |OCSP_REQUEST|. Signing also sets the -// |requestorName| to the subject name of an optional signers certificate and -// includes one or more optional certificates in the request. -// This will fail if a signature in the |OCSP_REQUEST| already exists. +// OCSP_request_sign signs the OCSP request |req| using |key| and |dgst|. |key| +// MUST be the private key of |signer|. One or more optional certificates can be +// added to |resp| with |certs|. This function will fail if a signature in |req| +// already exists. +// +// Note: 1. The OCSP requester is identified by the subject name from |signer| +// and included in |req|. +// 2. All certificates in |certs| are added to |req| by default. Setting +// |OCSP_NOCERTS| excludes certificates from being added in |req| and +// ignores the |certs| parameter. OPENSSL_EXPORT int OCSP_request_sign(OCSP_REQUEST *req, X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, STACK_OF(X509) *certs, @@ -385,6 +401,24 @@ OPENSSL_EXPORT int OCSP_id_get0_info(ASN1_OCTET_STRING **nameHash, // OCSP_basic_add1_cert adds |cert| to the |resp|. OPENSSL_EXPORT int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert); +// OCSP_basic_sign signs the OCSP response |resp| using |key| and |dgst|. |key| +// MUST be the private key of |signer|. One or more optional certificates can be +// added to |resp| with |certs|. +// +// Note: 1. By default, the OCSP responder is identified by the subject name +// from |signer| and included in |resp|. Users can set +// |OCSP_RESPID_KEY| with |flags|, if they wish for the responder to +// be identified by the hash of |signer|'s public key instead. +// 2. All certificates in |certs| are added to |resp| by default. Setting +// |OCSP_NOCERTS| excludes certificates from being added in |resp| and +// ignores the |certs| parameter. +// 3. The |producedAt| time field is set to the current time by default. +// Setting |OCSP_NOTIME| excludes setting the |producedAt| time field +// in |resp| and leaves it empty. +OPENSSL_EXPORT int OCSP_basic_sign(OCSP_BASICRESP *resp, X509 *signer, + EVP_PKEY *key, const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); + // OCSP_SINGLERESP_get0_id returns the |OCSP_CERTID| within |x|. OPENSSL_EXPORT const OCSP_CERTID *OCSP_SINGLERESP_get0_id( const OCSP_SINGLERESP *x);