Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCSP openssl compat fixes #8498

Merged
merged 14 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 165 additions & 39 deletions src/ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,13 +727,23 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
WOLFSSL_CERT_MANAGER* cm = NULL;
int ret = -1;
DerBuffer* derCert = NULL;
int dgstType;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert *cert = NULL;
#else
DecodedCert cert[1];
#endif

(void)dgst;
if (dgst == NULL) {
dgstType = WC_HASH_TYPE_SHA;
}
else if (wolfSSL_EVP_get_hashinfo(dgst, &dgstType, NULL) !=
WOLFSSL_SUCCESS) {
return NULL;
}

if (dgstType != OCSP_DIGEST)
return NULL;

cm = wolfSSL_CertManagerNew();
if (cm == NULL
Expand Down Expand Up @@ -785,6 +795,7 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
goto out;
}
else {
certId->hashAlgoOID = wc_HashGetOID(OCSP_DIGEST);
XMEMCPY(certId->issuerHash, cert->issuerHash, OCSP_DIGEST_SIZE);
XMEMCPY(certId->issuerKeyHash, cert->issuerKeyHash, OCSP_DIGEST_SIZE);
XMEMCPY(certId->status->serial, cert->serial, (size_t)cert->serialSz);
Expand Down Expand Up @@ -822,6 +833,78 @@ void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
wolfSSL_OCSP_RESPONSE_free(basicResponse);
}

/* Calculate ancode CertID DER encoding following RFC 6960:
CertID ::= SEQUENCE {
hashAlgorithm AlgorithmIdentifier,
issuerNameHash OCTET STRING,
issuerKeyHash OCTET STRING,
serialNumber CertificateSerialNumber }
*/
static int OcspEncodeCertID(WOLFSSL_OCSP_CERTID* id, byte* output,
word32* totalSz, word32* intSize)
{
word32 idx = 0;
int ret;

if (id == NULL || totalSz == NULL || intSize == NULL ||
(output != NULL && (*totalSz == 0 || *totalSz <= *intSize)))
return BAD_FUNC_ARG;

if (output != NULL) {
ret = SetSequence(*intSize, output);
if (ret < 0)
return ret;
idx += ret;
}

ret = SetAlgoID(id->hashAlgoOID, ((output != NULL) ? output + idx : output),
oidHashType, 0);
if (ret <= 0)
return -1;
idx += ret;

/* issuerNameHash */
ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output));
if (ret < 0)
return ret;
idx += ret;
if (output != NULL)
XMEMCPY(output + idx, id->issuerHash, OCSP_DIGEST_SIZE);
idx += OCSP_DIGEST_SIZE;

/* issuerKeyHash */
ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output));
if (ret < 0)
return ret;
idx += ret;
if (output != NULL)
XMEMCPY(output + idx, id->issuerKeyHash, OCSP_DIGEST_SIZE);
idx += OCSP_DIGEST_SIZE;

/* serialNumber */
ret = SetASNInt(id->status->serialSz, id->status->serial[0], ((output != NULL) ? output + idx : output));
if (ret < 0)
return ret;
idx += ret;
if (output != NULL)
XMEMCPY(output + idx, id->status->serial, id->status->serialSz);
idx += id->status->serialSz;

if (output == NULL) {
*intSize = idx;
ret = SetSequence(idx, NULL);
if (ret < 0)
return ret;
idx += ret;
*totalSz = idx;
}
else if (idx != *totalSz) {
return BUFFER_E;
}

return 0;
}

static int OcspRespIdMatches(OcspResponse* resp, const byte* NameHash,
const byte* keyHash)
{
Expand Down Expand Up @@ -1284,67 +1367,110 @@ int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,

int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data)
{
if (id == NULL || data == NULL)
return WOLFSSL_FAILURE;
int allocated = 0;
word32 derSz = 0;
word32 intSz = 0;
int ret;
WOLFSSL_ENTER("wolfSSL_i2d_OCSP_CERTID");

if (id == NULL)
return -1;

if (*data != NULL) {
XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize);
*data = *data + id->rawCertIdSize;
if (id->rawCertId != NULL) {
derSz = id->rawCertIdSize;
}
else {
*data = (unsigned char*)XMALLOC((size_t)id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL);
ret = OcspEncodeCertID(id, NULL, &derSz, &intSz);
if (ret != 0) {
WOLFSSL_MSG("Failed to calculate CertID size");
return -1;
}
}

if (data == NULL) {
return derSz;
}

if (*data == NULL) {
/* Allocate buffer for DER encoding */
*data = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
if (*data == NULL) {
return WOLFSSL_FAILURE;
WOLFSSL_MSG("Failed to allocate memory for CertID DER encoding");
return -1;
}
allocated = 1;
}

if (id->rawCertId != NULL) {
XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
}
else {
ret = OcspEncodeCertID(id, *data, &derSz, &intSz);
if (ret < 0) {
WOLFSSL_MSG("Failed to encode CertID");
if (allocated) {
XFREE(*data, NULL, DYNAMIC_TYPE_OPENSSL);
*data = NULL;
}
return -1;
}
XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize);
}

return id->rawCertIdSize;
if (!allocated)
*data += derSz;

return derSz;
}

WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut,
const unsigned char** derIn,
int length)
{
WOLFSSL_OCSP_CERTID *cid = NULL;
int isAllocated = 0;
word32 idx = 0;
int ret;

if ((cidOut != NULL) && (derIn != NULL) && (*derIn != NULL) &&
(length > 0)) {
if (derIn == NULL || *derIn == NULL || length <= 0)
return NULL;

if (cidOut != NULL && *cidOut != NULL) {
cid = *cidOut;
FreeOcspEntry(cid, NULL);
}
else {
cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL,
DYNAMIC_TYPE_OPENSSL);
if (cid == NULL)
return NULL;
isAllocated = 1;
}

/* If a NULL is passed we allocate the memory for the caller. */
if (cid == NULL) {
cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(*cid), NULL,
DYNAMIC_TYPE_OPENSSL);
}
else if (cid->rawCertId != NULL) {
XFREE(cid->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL);
cid->rawCertId = NULL;
cid->rawCertIdSize = 0;
}

if (cid != NULL) {
cid->rawCertId = (byte*)XMALLOC((size_t)length + 1, NULL, DYNAMIC_TYPE_OPENSSL);
if (cid->rawCertId != NULL) {
XMEMCPY(cid->rawCertId, *derIn, (size_t)length);
cid->rawCertIdSize = length;

/* Per spec. advance past the data that is being returned
* to the caller. */
*cidOut = cid;
*derIn = *derIn + length;
XMEMSET(cid, 0, sizeof(WOLFSSL_OCSP_CERTID));
cid->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
DYNAMIC_TYPE_OCSP_STATUS);
if (cid->status == NULL) {
XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
XMEMSET(cid->status, 0, sizeof(CertStatus));
cid->ownStatus = 1;

return cid;
}
ret = OcspDecodeCertID(*derIn, &idx, length, cid);
if (ret != 0) {
FreeOcspEntry(cid, NULL);
if (isAllocated) {
XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
}
return NULL;
}

if ((cid != NULL) && ((cidOut == NULL) || (cid != *cidOut))) {
XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
}
*derIn += idx;

return NULL;
if (isAllocated && cidOut != NULL)
*cidOut = cid;

return cid;
}

const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(
Expand Down
12 changes: 5 additions & 7 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -71324,7 +71324,8 @@ static int test_wolfSSL_OCSP_id_get0_info(void)
{
EXPECT_DECLS;
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)) && \
defined(HAVE_OCSP) && !defined(NO_FILESYSTEM) && !defined(NO_RSA)
defined(HAVE_OCSP) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \
!defined(WOLFSSL_SM2) && !defined(WOLFSSL_SM3)
X509* cert = NULL;
X509* issuer = NULL;
OCSP_CERTID* id = NULL;
Expand Down Expand Up @@ -71456,10 +71457,9 @@ static int test_wolfSSL_d2i_OCSP_CERTID(void)
WOLFSSL_OCSP_CERTID* certId = NULL;
ExpectNotNull(certId = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr,
sizeof(rawCertId)));
ExpectIntEQ(certId->rawCertIdSize, sizeof(rawCertId));
if (certId != NULL) {
XFREE(certId->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL);
XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
wolfSSL_OCSP_CERTID_free(certId);
}
}

Expand All @@ -71477,10 +71477,9 @@ static int test_wolfSSL_d2i_OCSP_CERTID(void)
ExpectNotNull(certIdGood = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr,
sizeof(rawCertId)));
ExpectPtrEq(certIdGood, certId);
ExpectIntEQ(certId->rawCertIdSize, sizeof(rawCertId));
if (certId != NULL) {
XFREE(certId->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL);
XFREE(certId, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL_OCSP_CERTID_free(certId);
certId = NULL;
}
}
Expand All @@ -71489,8 +71488,6 @@ static int test_wolfSSL_d2i_OCSP_CERTID(void)
* always be returned. */
{
WOLFSSL_OCSP_CERTID* certId = NULL;
ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(NULL, &rawCertIdPtr,
sizeof(rawCertId)));
ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(&certId, NULL,
sizeof(rawCertId)));
ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr, 0));
Expand Down Expand Up @@ -95500,6 +95497,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_ocsp_status_callback),
TEST_DECL(test_ocsp_basic_verify),
TEST_DECL(test_ocsp_response_parsing),
TEST_DECL(test_ocsp_certid_enc_dec),
/* This test needs to stay at the end to clean up any caches allocated. */
TEST_DECL(test_wolfSSL_Cleanup)
};
Expand Down
2 changes: 1 addition & 1 deletion tests/api/create_ocsp_test_blobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ def create_bad_response(rd: dict) -> bytes:
},
]

with open('./tests/api/ocsp_test_blobs.h', 'w') as f:
with open('./tests/api/test_ocsp_test_blobs.h', 'w') as f:
f.write(
"""/*
* This file is generated automatically by running ./tests/api/create_ocsp_test_blobs.py.
Expand Down
Loading
Loading