forked from wolfSSL/wolfssl
Merge pull request #8498 from rizlik/ocsp_fixes
OCSP openssl compat fixes
This commit is contained in:
202
src/ocsp.c
202
src/ocsp.c
@ -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
|
||||
@ -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);
|
||||
@ -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)
|
||||
{
|
||||
@ -1284,22 +1367,59 @@ 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 (*data != NULL) {
|
||||
XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize);
|
||||
*data = *data + id->rawCertIdSize;
|
||||
if (id == NULL)
|
||||
return -1;
|
||||
|
||||
if (id->rawCertId != NULL) {
|
||||
derSz = id->rawCertIdSize;
|
||||
}
|
||||
else {
|
||||
*data = (unsigned char*)XMALLOC((size_t)id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
if (*data == NULL) {
|
||||
return WOLFSSL_FAILURE;
|
||||
ret = OcspEncodeCertID(id, NULL, &derSz, &intSz);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("Failed to calculate CertID size");
|
||||
return -1;
|
||||
}
|
||||
XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize);
|
||||
}
|
||||
|
||||
return id->rawCertIdSize;
|
||||
if (data == NULL) {
|
||||
return derSz;
|
||||
}
|
||||
|
||||
if (*data == NULL) {
|
||||
/* Allocate buffer for DER encoding */
|
||||
*data = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
if (*data == NULL) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allocated)
|
||||
*data += derSz;
|
||||
|
||||
return derSz;
|
||||
}
|
||||
|
||||
WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut,
|
||||
@ -1307,44 +1427,50 @@ WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut,
|
||||
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;
|
||||
|
||||
/* If a NULL is passed we allocate the memory for the caller. */
|
||||
if (cid == NULL) {
|
||||
cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(*cid), NULL,
|
||||
FreeOcspEntry(cid, NULL);
|
||||
}
|
||||
else {
|
||||
cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), 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)
|
||||
return NULL;
|
||||
isAllocated = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return cid;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
if ((cid != NULL) && ((cidOut == NULL) || (cid != *cidOut))) {
|
||||
ret = OcspDecodeCertID(*derIn, &idx, length, cid);
|
||||
if (ret != 0) {
|
||||
FreeOcspEntry(cid, NULL);
|
||||
if (isAllocated) {
|
||||
XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*derIn += idx;
|
||||
|
||||
if (isAllocated && cidOut != NULL)
|
||||
*cidOut = cid;
|
||||
|
||||
return cid;
|
||||
}
|
||||
|
||||
const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(
|
||||
|
12
tests/api.c
12
tests/api.c
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
@ -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)
|
||||
};
|
||||
|
@ -401,7 +401,7 @@ if __name__ == '__main__':
|
||||
},
|
||||
]
|
||||
|
||||
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.
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <wolfssl/ocsp.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
|
||||
#if defined(HAVE_OCSP)
|
||||
#if defined(HAVE_OCSP) && !defined(NO_SHA)
|
||||
struct ocsp_cb_ctx {
|
||||
byte* response;
|
||||
int responseSz;
|
||||
@ -158,12 +158,12 @@ int test_ocsp_response_parsing(void)
|
||||
|
||||
return EXPECT_SUCCESS();
|
||||
}
|
||||
#else /* HAVE_OCSP */
|
||||
#else /* HAVE_OCSP && !NO_SHA */
|
||||
int test_ocsp_response_parsing(void)
|
||||
{
|
||||
return TEST_SKIPPED;
|
||||
}
|
||||
#endif /* HAVE_OCSP */
|
||||
#endif /* HAVE_OCSP && !NO_SHA */
|
||||
|
||||
#if defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA))
|
||||
static int test_ocsp_create_x509store(WOLFSSL_X509_STORE** store,
|
||||
@ -222,7 +222,7 @@ int test_ocsp_basic_verify(void)
|
||||
ExpectIntEQ(response->responseStatus, 0);
|
||||
ExpectIntEQ(response->responderIdType, OCSP_RESPONDER_ID_KEY);
|
||||
ExpectBufEQ(response->responderId.keyHash, cert.subjectKeyHash,
|
||||
OCSP_DIGEST_SIZE);
|
||||
OCSP_RESPONDER_ID_KEY_SZ);
|
||||
wolfSSL_OCSP_RESPONSE_free(response);
|
||||
|
||||
/* decoding with no embedded certificates */
|
||||
@ -592,3 +592,71 @@ int test_ocsp_status_callback(void)
|
||||
&& defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
|
||||
!defined(WOLFSSL_NO_TLS12) \
|
||||
&& defined(OPENSSL_ALL) */
|
||||
|
||||
#if !defined(NO_SHA) && defined(OPENSSL_ALL) && defined(HAVE_OCSP) && \
|
||||
!defined(WOLFSSL_SM3) && !defined(WOLFSSL_SM2)
|
||||
int test_ocsp_certid_enc_dec(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
WOLFSSL_OCSP_CERTID* certIdDec = NULL;
|
||||
WOLFSSL_OCSP_CERTID* certId = NULL;
|
||||
WOLFSSL_X509* subject = NULL;
|
||||
WOLFSSL_X509* issuer = NULL;
|
||||
unsigned char* temp = NULL;
|
||||
unsigned char* der2 = NULL;
|
||||
unsigned char* der = NULL;
|
||||
int derSz = 0, derSz1 = 0;
|
||||
|
||||
/* Load test certificates */
|
||||
ExpectNotNull(
|
||||
subject = wolfSSL_X509_load_certificate_file(
|
||||
"./certs/ocsp/intermediate1-ca-cert.pem", WOLFSSL_FILETYPE_PEM));
|
||||
ExpectNotNull(issuer = wolfSSL_X509_load_certificate_file(
|
||||
"./certs/ocsp/root-ca-cert.pem", WOLFSSL_FILETYPE_PEM));
|
||||
|
||||
/* Create CERTID from certificates */
|
||||
ExpectNotNull(certId = wolfSSL_OCSP_cert_to_id(NULL, subject, issuer));
|
||||
|
||||
/* get len */
|
||||
ExpectIntGT(derSz = wolfSSL_i2d_OCSP_CERTID(certId, NULL), 0);
|
||||
|
||||
/* encode it */
|
||||
ExpectIntGT(derSz1 = wolfSSL_i2d_OCSP_CERTID(certId, &der), 0);
|
||||
ExpectIntEQ(derSz, derSz1);
|
||||
|
||||
if (EXPECT_SUCCESS())
|
||||
temp = der2 = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
ExpectNotNull(der2);
|
||||
/* encode without allocation */
|
||||
ExpectIntGT(derSz1 = wolfSSL_i2d_OCSP_CERTID(certId, &der2), 0);
|
||||
ExpectIntEQ(derSz, derSz1);
|
||||
ExpectPtrEq(der2, temp + derSz);
|
||||
ExpectBufEQ(der, temp, derSz);
|
||||
XFREE(temp, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
|
||||
/* save original */
|
||||
temp = der;
|
||||
/* decode it */
|
||||
ExpectNotNull(certIdDec = wolfSSL_d2i_OCSP_CERTID(NULL,
|
||||
(const unsigned char**)&der, derSz));
|
||||
/* check ptr is advanced */
|
||||
ExpectPtrEq(der, temp + derSz);
|
||||
der = der2;
|
||||
XFREE(temp, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
|
||||
/* compare */
|
||||
ExpectIntEQ(wolfSSL_OCSP_id_cmp(certId, certIdDec), 0);
|
||||
|
||||
wolfSSL_OCSP_CERTID_free(certId);
|
||||
wolfSSL_OCSP_CERTID_free(certIdDec);
|
||||
wolfSSL_X509_free(subject);
|
||||
wolfSSL_X509_free(issuer);
|
||||
|
||||
return EXPECT_SUCCESS();
|
||||
}
|
||||
#else /* !NO_SHA && OPENSSL_ALL && HAVE_OCSP && !WOLFSSL_SM3 && !WOLFSSL_SM2 */
|
||||
int test_ocsp_certid_enc_dec(void)
|
||||
{
|
||||
return TEST_SKIPPED;
|
||||
}
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
#ifndef WOLFSSL_TEST_OCSP_H
|
||||
#define WOLFSSL_TEST_OCSP_H
|
||||
|
||||
int test_ocsp_certid_enc_dec(void);
|
||||
int test_ocsp_status_callback(void);
|
||||
int test_ocsp_basic_verify(void);
|
||||
int test_ocsp_response_parsing(void);
|
||||
|
@ -36374,17 +36374,7 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,
|
||||
static const ASNItem singleResponseASN[] = {
|
||||
/* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
|
||||
/* certId */
|
||||
/* CID_SEQ */ { 1, ASN_SEQUENCE, 1, 1, 0 },
|
||||
/* hashAlgorithm */
|
||||
/* CID_HASHALGO_SEQ */ { 2, ASN_SEQUENCE, 1, 1, 0 },
|
||||
/* CID_HASHALGO_OID */ { 3, ASN_OBJECT_ID, 0, 0, 0 },
|
||||
/* CID_HASHALGO_NULL */ { 3, ASN_TAG_NULL, 0, 0, 1 },
|
||||
/* issuerNameHash */
|
||||
/* CID_ISSUERHASH */ { 2, ASN_OCTET_STRING, 0, 0, 0 },
|
||||
/* issuerKeyHash */
|
||||
/* CID_ISSUERKEYHASH */ { 2, ASN_OCTET_STRING, 0, 0, 0 },
|
||||
/* serialNumber */
|
||||
/* CID_SERIAL */ { 2, ASN_INTEGER, 0, 0, 0 },
|
||||
/* CID_SEQ */ { 1, ASN_SEQUENCE, 1, 0, 0 },
|
||||
/* certStatus - CHOICE */
|
||||
/* good [0] IMPLICIT NULL */
|
||||
/* CS_GOOD */ { 1, ASN_CONTEXT_SPECIFIC | 0, 0, 0, 2 },
|
||||
@ -36410,12 +36400,6 @@ static const ASNItem singleResponseASN[] = {
|
||||
enum {
|
||||
SINGLERESPONSEASN_IDX_SEQ = 0,
|
||||
SINGLERESPONSEASN_IDX_CID_SEQ,
|
||||
SINGLERESPONSEASN_IDX_CID_HASHALGO_SEQ,
|
||||
SINGLERESPONSEASN_IDX_CID_HASHALGO_OID,
|
||||
SINGLERESPONSEASN_IDX_CID_HASHALGO_NULL,
|
||||
SINGLERESPONSEASN_IDX_CID_ISSUERHASH,
|
||||
SINGLERESPONSEASN_IDX_CID_ISSUERKEYHASH,
|
||||
SINGLERESPONSEASN_IDX_CID_SERIAL,
|
||||
SINGLERESPONSEASN_IDX_CS_GOOD,
|
||||
SINGLERESPONSEASN_IDX_CS_REVOKED,
|
||||
SINGLERESPONSEASN_IDX_CS_REVOKED_TIME,
|
||||
@ -36430,13 +36414,139 @@ enum {
|
||||
|
||||
/* Number of items in ASN.1 template for OCSP single response. */
|
||||
#define singleResponseASN_Length (sizeof(singleResponseASN) / sizeof(ASNItem))
|
||||
|
||||
static const ASNItem certIDASNItems[] = {
|
||||
/* hashAlgorithm */
|
||||
/* CID_HASHALGO_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
|
||||
/* CID_HASHALGO_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
|
||||
/* CID_HASHALGO_NULL */ { 1, ASN_TAG_NULL, 0, 0, 1 },
|
||||
/* issuerNameHash */
|
||||
/* CID_ISSUERHASH */ { 0, ASN_OCTET_STRING, 0, 0, 0 },
|
||||
/* issuerKeyHash */
|
||||
/* CID_ISSUERKEYHASH */ { 0, ASN_OCTET_STRING, 0, 0, 0 },
|
||||
/* serialNumber */
|
||||
/* CID_SERIAL */ { 0, ASN_INTEGER, 0, 0, 0 },
|
||||
};
|
||||
|
||||
enum {
|
||||
CERTIDASN_IDX_CID_HASHALGO_SEQ,
|
||||
CERTIDASN_IDX_CID_HASHALGO_OID,
|
||||
CERTIDASN_IDX_CID_HASHALGO_NULL,
|
||||
CERTIDASN_IDX_CID_ISSUERHASH,
|
||||
CERTIDASN_IDX_CID_ISSUERKEYHASH,
|
||||
CERTIDASN_IDX_CID_SERIAL,
|
||||
};
|
||||
|
||||
#define certidasn_Length (sizeof(certIDASNItems) / sizeof(ASNItem))
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||
static int OcspDecodeCertIDInt(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
OcspEntry* entry)
|
||||
{
|
||||
int length;
|
||||
word32 oid;
|
||||
int ret;
|
||||
/* Hash algorithm */
|
||||
ret = GetAlgoId(input, inOutIdx, &oid, oidHashType, inSz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
entry->hashAlgoOID = oid;
|
||||
/* Save reference to the hash of CN */
|
||||
ret = GetOctetString(input, inOutIdx, &length, inSz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (length != OCSP_DIGEST_SIZE)
|
||||
return ASN_PARSE_E;
|
||||
XMEMCPY(entry->issuerHash, input + *inOutIdx, length);
|
||||
*inOutIdx += length;
|
||||
/* Save reference to the hash of the issuer public key */
|
||||
ret = GetOctetString(input, inOutIdx, &length, inSz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (length != OCSP_DIGEST_SIZE)
|
||||
return ASN_PARSE_E;
|
||||
XMEMCPY(entry->issuerKeyHash, input + *inOutIdx, length);
|
||||
*inOutIdx += length;
|
||||
|
||||
/* Get serial number */
|
||||
if (wc_GetSerialNumber(input, inOutIdx, entry->status->serial,
|
||||
&entry->status->serialSz, inSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int OcspDecodeCertIDInt(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
OcspEntry* entry)
|
||||
{
|
||||
DECL_ASNGETDATA(dataASN, certidasn_Length);
|
||||
word32 issuerKeyHashLen = OCSP_DIGEST_SIZE;
|
||||
word32 issuerHashLen = OCSP_DIGEST_SIZE;
|
||||
word32 serialSz = EXTERNAL_SERIAL_SIZE;
|
||||
word32 digestSz;
|
||||
int ret = 0;
|
||||
|
||||
WOLFSSL_ENTER("DecodeCertIdTemplate");
|
||||
CALLOC_ASNGETDATA(dataASN, certidasn_Length, ret, NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
GetASN_OID(&dataASN[CERTIDASN_IDX_CID_HASHALGO_OID], oidHashType);
|
||||
GetASN_Buffer(&dataASN[CERTIDASN_IDX_CID_ISSUERHASH], entry->issuerHash,
|
||||
&issuerHashLen);
|
||||
GetASN_Buffer(&dataASN[CERTIDASN_IDX_CID_ISSUERKEYHASH],
|
||||
entry->issuerKeyHash, &issuerKeyHashLen);
|
||||
GetASN_Buffer(&dataASN[CERTIDASN_IDX_CID_SERIAL], entry->status->serial,
|
||||
&serialSz);
|
||||
ret = GetASN_Items(certIDASNItems, dataASN, certidasn_Length,
|
||||
1, input, inOutIdx, inSz);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
entry->status->serialSz = serialSz;
|
||||
entry->hashAlgoOID =
|
||||
dataASN[CERTIDASN_IDX_CID_HASHALGO_OID].data.oid.sum;
|
||||
digestSz = wc_HashGetDigestSize(wc_OidGetHash(entry->hashAlgoOID));
|
||||
if (issuerKeyHashLen != digestSz || issuerHashLen != digestSz) {
|
||||
ret = ASN_PARSE_E;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
FREE_ASNGETDATA(dataASN, NULL);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int OcspDecodeCertID(const byte *input, word32 *inOutIdx, word32 inSz,
|
||||
OcspEntry *entry)
|
||||
{
|
||||
word32 seqIdx = 0;
|
||||
int len = inSz;
|
||||
int ret;
|
||||
|
||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||
ret = GetSequence(input, inOutIdx, &len, inSz);
|
||||
#else
|
||||
ret = GetASN_Sequence(input, inOutIdx, &len, inSz, 0);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ASN_PARSE_E;
|
||||
ret = OcspDecodeCertIDInt(input + *inOutIdx, &seqIdx, len, entry);
|
||||
if (ret < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (seqIdx != (word32)len)
|
||||
return ASN_PARSE_E;
|
||||
*inOutIdx += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
||||
int wrapperSz, OcspEntry* single)
|
||||
{
|
||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||
word32 idx = *ioIndex, prevIndex, oid, localIdx, certIdIdx;
|
||||
word32 idx = *ioIndex, prevIndex, localIdx, certIdIdx;
|
||||
int length;
|
||||
int ret;
|
||||
byte tag;
|
||||
@ -36454,31 +36564,8 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
||||
if (GetSequence(source, &idx, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
single->rawCertId = source + certIdIdx;
|
||||
/* Hash algorithm */
|
||||
ret = GetAlgoId(source, &idx, &oid, oidIgnoreType, size);
|
||||
ret = OcspDecodeCertIDInt(source, &idx, size, single);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
single->hashAlgoOID = oid;
|
||||
/* Save reference to the hash of CN */
|
||||
ret = GetOctetString(source, &idx, &length, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (length > (int)sizeof(single->issuerHash))
|
||||
return BUFFER_E;
|
||||
XMEMCPY(single->issuerHash, source + idx, length);
|
||||
idx += length;
|
||||
/* Save reference to the hash of the issuer public key */
|
||||
ret = GetOctetString(source, &idx, &length, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (length > (int)sizeof(single->issuerKeyHash))
|
||||
return BUFFER_E;
|
||||
XMEMCPY(single->issuerKeyHash, source + idx, length);
|
||||
idx += length;
|
||||
|
||||
/* Get serial number */
|
||||
if (wc_GetSerialNumber(source, &idx, single->status->serial,
|
||||
&single->status->serialSz, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
single->rawCertIdSize = idx - certIdIdx;
|
||||
|
||||
@ -36591,13 +36678,10 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
||||
#else /* WOLFSSL_ASN_TEMPLATE */
|
||||
DECL_ASNGETDATA(dataASN, singleResponseASN_Length);
|
||||
int ret = 0;
|
||||
word32 ocspDigestSize = OCSP_DIGEST_SIZE;
|
||||
CertStatus* cs = NULL;
|
||||
word32 serialSz;
|
||||
word32 issuerHashLen;
|
||||
word32 issuerKeyHashLen;
|
||||
word32 thisDateLen;
|
||||
word32 nextDateLen;
|
||||
word32 certIdSeqIdx;
|
||||
|
||||
(void)wrapperSz;
|
||||
|
||||
@ -36606,25 +36690,12 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
||||
CALLOC_ASNGETDATA(dataASN, singleResponseASN_Length, ret, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
/* Certificate Status field. */
|
||||
cs = single->status;
|
||||
|
||||
/* Set maximum lengths for data. */
|
||||
issuerHashLen = OCSP_DIGEST_SIZE;
|
||||
issuerKeyHashLen = OCSP_DIGEST_SIZE;
|
||||
serialSz = EXTERNAL_SERIAL_SIZE;
|
||||
thisDateLen = MAX_DATE_SIZE;
|
||||
nextDateLen = MAX_DATE_SIZE;
|
||||
|
||||
/* Set OID type, buffers to hold data and variables to hold size. */
|
||||
GetASN_OID(&dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID],
|
||||
oidHashType);
|
||||
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_CID_ISSUERHASH],
|
||||
single->issuerHash, &issuerHashLen);
|
||||
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_CID_ISSUERKEYHASH],
|
||||
single->issuerKeyHash, &issuerKeyHashLen);
|
||||
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_CID_SERIAL], cs->serial,
|
||||
&serialSz);
|
||||
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_THISUPDATE_GT],
|
||||
cs->thisDate, &thisDateLen);
|
||||
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_NEXTUPDATE_GT],
|
||||
@ -36635,27 +36706,11 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
||||
1, source, ioIndex, size);
|
||||
}
|
||||
if (ret == 0) {
|
||||
single->hashAlgoOID =
|
||||
dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID].data.oid.sum;
|
||||
ocspDigestSize = (word32)wc_HashGetDigestSize(
|
||||
wc_OidGetHash((int)single->hashAlgoOID));
|
||||
}
|
||||
/* Validate the issuer hash length is the size required. */
|
||||
if ((ret == 0) && (issuerHashLen != ocspDigestSize)) {
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
/* Validate the issuer key hash length is the size required. */
|
||||
if (ret == 0) {
|
||||
if (issuerKeyHashLen != ocspDigestSize) {
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
certIdSeqIdx = 0;
|
||||
ret = OcspDecodeCertIDInt(dataASN[SINGLERESPONSEASN_IDX_CID_SEQ].data.ref.data,
|
||||
&certIdSeqIdx, dataASN[SINGLERESPONSEASN_IDX_CID_SEQ].data.ref.length, single);
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Store serial size. */
|
||||
cs->serialSz = (int)serialSz;
|
||||
/* Set the hash algorithm OID */
|
||||
single->hashAlgoOID =
|
||||
dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID].data.oid.sum;
|
||||
|
||||
/* Determine status by which item was found. */
|
||||
if (dataASN[SINGLERESPONSEASN_IDX_CS_GOOD].tag != 0) {
|
||||
@ -36964,7 +37019,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
||||
/* compute the hash of the name */
|
||||
resp->responderIdType = OCSP_RESPONDER_ID_NAME;
|
||||
ret = CalcHashId_ex(source + idx, length,
|
||||
resp->responderId.nameHash, WC_SHA);
|
||||
resp->responderId.nameHash, OCSP_RESPONDER_ID_HASH_TYPE);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
idx += length;
|
||||
@ -36978,7 +37033,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
||||
if (GetOctetString(source, &idx, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (length != KEYID_SIZE)
|
||||
if (length != OCSP_RESPONDER_ID_KEY_SZ)
|
||||
return ASN_PARSE_E;
|
||||
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
|
||||
XMEMCPY(resp->responderId.keyHash, source + idx, length);
|
||||
@ -37041,7 +37096,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
||||
int ret = 0;
|
||||
byte version;
|
||||
word32 dateSz = 0;
|
||||
word32 responderByKeySz = KEYID_SIZE;
|
||||
word32 responderByKeySz = OCSP_RESPONDER_ID_KEY_SZ;
|
||||
word32 idx = *ioIndex;
|
||||
OcspEntry* single = NULL;
|
||||
|
||||
@ -37084,10 +37139,11 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
||||
ret = CalcHashId_ex(
|
||||
dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.data,
|
||||
dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.length,
|
||||
resp->responderId.nameHash, WC_SHA);
|
||||
resp->responderId.nameHash, OCSP_RESPONDER_ID_HASH_TYPE);
|
||||
} else {
|
||||
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
|
||||
if (dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT].length != KEYID_SIZE) {
|
||||
if (dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT].length
|
||||
!= OCSP_RESPONDER_ID_KEY_SZ) {
|
||||
ret = ASN_PARSE_E;
|
||||
} else {
|
||||
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
|
||||
@ -37240,10 +37296,14 @@ enum {
|
||||
static int OcspRespIdMatch(OcspResponse *resp, const byte *NameHash,
|
||||
const byte *keyHash)
|
||||
{
|
||||
if (resp->responderIdType == OCSP_RESPONDER_ID_INVALID)
|
||||
return 0;
|
||||
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME)
|
||||
return XMEMCMP(NameHash, resp->responderId.nameHash,
|
||||
SIGNER_DIGEST_SIZE) == 0;
|
||||
return XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0;
|
||||
/* OCSP_RESPONDER_ID_KEY */
|
||||
return ((int)KEYID_SIZE == OCSP_RESPONDER_ID_KEY_SZ) &&
|
||||
XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0;
|
||||
}
|
||||
|
||||
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||
@ -37282,7 +37342,7 @@ static Signer *OcspFindSigner(OcspResponse *resp, WOLFSSL_CERT_MANAGER *cm)
|
||||
if (s)
|
||||
return s;
|
||||
}
|
||||
else {
|
||||
else if ((int)KEYID_SIZE == OCSP_RESPONDER_ID_KEY_SZ) {
|
||||
s = GetCAByKeyHash(cm, resp->responderId.keyHash);
|
||||
if (s)
|
||||
return s;
|
||||
|
@ -2707,6 +2707,14 @@ struct CertStatus {
|
||||
|
||||
typedef struct OcspEntry OcspEntry;
|
||||
|
||||
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
|
||||
#define OCSP_DIGEST WC_HASH_TYPE_SM3
|
||||
#elif defined(NO_SHA)
|
||||
#define OCSP_DIGEST WC_HASH_TYPE_SHA256
|
||||
#else
|
||||
#define OCSP_DIGEST WC_HASH_TYPE_SHA
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
|
||||
#define OCSP_DIGEST_SIZE WC_SM3_DIGEST_SIZE
|
||||
#elif defined(NO_SHA)
|
||||
@ -2732,6 +2740,12 @@ struct OcspEntry
|
||||
WC_BITFIELD used:1; /* entry used */
|
||||
};
|
||||
|
||||
#define OCSP_RESPONDER_ID_KEY_SZ 20
|
||||
#if !defined(NO_SHA)
|
||||
#define OCSP_RESPONDER_ID_HASH_TYPE WC_SHA
|
||||
#else
|
||||
#define OCSP_RESPONDER_ID_HASH_TYPE WC_SHA256
|
||||
#endif
|
||||
enum responderIdType {
|
||||
OCSP_RESPONDER_ID_INVALID = 0,
|
||||
OCSP_RESPONDER_ID_NAME = 1,
|
||||
@ -2750,7 +2764,7 @@ struct OcspResponse {
|
||||
|
||||
enum responderIdType responderIdType;
|
||||
union {
|
||||
byte keyHash[KEYID_SIZE];
|
||||
byte keyHash[OCSP_RESPONDER_ID_KEY_SZ];
|
||||
byte nameHash[KEYID_SIZE];
|
||||
} responderId ;
|
||||
|
||||
@ -2817,7 +2831,8 @@ WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output,
|
||||
|
||||
|
||||
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp);
|
||||
|
||||
WOLFSSL_LOCAL int OcspDecodeCertID(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
OcspEntry* entry);
|
||||
|
||||
#endif /* HAVE_OCSP */
|
||||
|
||||
|
Reference in New Issue
Block a user