Skip to content

Commit

Permalink
Merge pull request wolfSSL#8498 from rizlik/ocsp_fixes
Browse files Browse the repository at this point in the history
OCSP openssl compat fixes
  • Loading branch information
SparkiDev authored Feb 28, 2025
2 parents d63a180 + 194db7e commit 4f8a39c
Show file tree
Hide file tree
Showing 7 changed files with 406 additions and 138 deletions.
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 @@ -66217,7 +66217,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 @@ -66349,10 +66350,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 @@ -66370,10 +66370,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 @@ -66382,8 +66381,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 @@ -90451,6 +90448,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

0 comments on commit 4f8a39c

Please sign in to comment.