Merge pull request #5197 from JacobBarthelmeh/OCSP

RSA-PSS with OCSP and add simple OCSP response der verify test case
pull/5573/head
Sean Parkinson 2022-09-13 15:10:00 +10:00 committed by GitHub
commit 38418b31f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 172 additions and 6 deletions

View File

@ -32,4 +32,7 @@ EXTRA_DIST += \
certs/ocsp/server5-key.pem \
certs/ocsp/server5-cert.pem \
certs/ocsp/root-ca-key.pem \
certs/ocsp/root-ca-cert.pem
certs/ocsp/root-ca-cert.pem \
certs/ocsp/test-response.der \
certs/ocsp/test-response-rsapss.der \
certs/ocsp/test-response-nointern.der

View File

@ -79,3 +79,27 @@ update_cert server2 "www2.wolfssl.com" intermediate1-ca
update_cert server3 "www3.wolfssl.com" intermediate2-ca v3_req2 07
update_cert server4 "www4.wolfssl.com" intermediate2-ca v3_req2 08 # REVOKED
update_cert server5 "www5.wolfssl.com" intermediate3-ca v3_req3 09
# Create response DER buffer for test
openssl ocsp -port 22221 -ndays 1000 -index index-ca-and-intermediate-cas.txt -rsigner ocsp-responder-cert.pem -rkey ocsp-responder-key.pem -CA root-ca-cert.pem -partial_chain &
PID=$!
openssl ocsp -issuer ./root-ca-cert.pem -cert ./intermediate1-ca-cert.pem -url http://localhost:22221/ -respout test-response.der -noverify
openssl ocsp -issuer ./root-ca-cert.pem -cert ./intermediate1-ca-cert.pem -url http://localhost:22221/ -respout test-response-nointern.der -no_intern -noverify
kill $PID
wait $PID
# now start up a responder that signs using rsa-pss
openssl ocsp -port 22221 -ndays 1000 -index index-ca-and-intermediate-cas.txt -rsigner ocsp-responder-cert.pem -rkey ocsp-responder-key.pem -CA root-ca-cert.pem -rsigopt rsa_padding_mode:pss &
PID=$!
openssl ocsp -issuer ./root-ca-cert.pem -cert ./intermediate1-ca-cert.pem -url http://localhost:22221/ -respout test-response-rsapss.der -noverify
# can verify with the following command
# openssl ocsp -respin test-response-nointern.der -CAfile root-ca-cert.pem -issuer intermediate1-ca-cert.pem
kill $PID
wait $PID
exit 0

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -826,6 +826,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
OcspResponse *resp = NULL;
word32 idx = 0;
int length = 0;
int ret;
if (data == NULL)
return NULL;
@ -867,7 +868,10 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
XMEMCPY(resp->source, *data, len);
resp->maxIdx = len;
if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) {
ret = OcspResponseDecode(resp, NULL, NULL, 1);
if (ret != 0 && ret != ASN_OCSP_CONFIRM_E) {
/* for just converting from a DER to an internal structure the CA may
* not yet be known to this function for signature verification */
wolfSSL_OCSP_RESPONSE_free(resp);
return NULL;
}

View File

@ -1605,6 +1605,94 @@ static int test_wolfSSL_CertManagerCheckOCSPResponse(void)
return 0;
}
static int test_wolfSSL_CheckOCSPResponse(void)
{
#if defined(HAVE_OCSP) && !defined(NO_RSA) && defined(OPENSSL_ALL)
const char* responseFile = "./certs/ocsp/test-response.der";
const char* responseNoInternFile = "./certs/ocsp/test-response-nointern.der";
const char* caFile = "./certs/ocsp/root-ca-cert.pem";
OcspResponse* res = NULL;
byte data[4096];
const unsigned char* pt;
int dataSz;
XFILE f;
WOLFSSL_OCSP_BASICRESP* bs;
WOLFSSL_X509_STORE* st;
WOLFSSL_X509* issuer;
printf(testingFmt, "wolfSSL_CheckOCSPResponse()");
f = XFOPEN(responseFile, "rb");
AssertTrue(f != XBADFILE);
dataSz = (word32)XFREAD(data, 1, sizeof(data), f);
AssertIntGT(dataSz, 0);
XFCLOSE(f);
pt = data;
res = wolfSSL_d2i_OCSP_RESPONSE(NULL, &pt, dataSz);
AssertNotNull(res);
issuer = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM);
AssertNotNull(issuer);
st = wolfSSL_X509_STORE_new();
AssertNotNull(st);
AssertIntEQ(wolfSSL_X509_STORE_add_cert(st, issuer), WOLFSSL_SUCCESS);
bs = wolfSSL_OCSP_response_get1_basic(res);
AssertNotNull(bs);
AssertIntEQ(wolfSSL_OCSP_basic_verify(bs, NULL, st, 0), WOLFSSL_SUCCESS);
wolfSSL_OCSP_BASICRESP_free(bs);
wolfSSL_OCSP_RESPONSE_free(res);
wolfSSL_X509_STORE_free(st);
wolfSSL_X509_free(issuer);
/* check loading a response with optional certs */
f = XFOPEN(responseNoInternFile, "rb");
AssertTrue(f != XBADFILE);
dataSz = (word32)XFREAD(data, 1, sizeof(data), f);
AssertIntGT(dataSz, 0);
XFCLOSE(f);
pt = data;
res = wolfSSL_d2i_OCSP_RESPONSE(NULL, &pt, dataSz);
AssertNotNull(res);
wolfSSL_OCSP_RESPONSE_free(res);
#if defined(WC_RSA_PSS)
{
const char* responsePssFile = "./certs/ocsp/test-response-rsapss.der";
/* check loading a response with RSA-PSS signature */
f = XFOPEN(responsePssFile, "rb");
AssertTrue(f != XBADFILE);
dataSz = (word32)XFREAD(data, 1, sizeof(data), f);
AssertIntGT(dataSz, 0);
XFCLOSE(f);
pt = data;
res = wolfSSL_d2i_OCSP_RESPONSE(NULL, &pt, dataSz);
AssertNotNull(res);
/* try to verify the response */
issuer = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM);
AssertNotNull(issuer);
st = wolfSSL_X509_STORE_new();
AssertNotNull(st);
AssertIntEQ(wolfSSL_X509_STORE_add_cert(st, issuer), WOLFSSL_SUCCESS);
bs = wolfSSL_OCSP_response_get1_basic(res);
AssertNotNull(bs);
AssertIntEQ(wolfSSL_OCSP_basic_verify(bs, NULL, st, 0), WOLFSSL_SUCCESS);
wolfSSL_OCSP_BASICRESP_free(bs);
wolfSSL_OCSP_RESPONSE_free(res);
wolfSSL_X509_STORE_free(st);
wolfSSL_X509_free(issuer);
}
#endif
printf(resultFmt, passed);
#endif /* HAVE_OCSP */
return 0;
}
static int test_wolfSSL_CertManagerLoadCABuffer(void)
{
int ret;
@ -58080,6 +58168,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_CTX_use_PrivateKey_file),
TEST_DECL(test_wolfSSL_CTX_load_verify_locations),
TEST_DECL(test_wolfSSL_CertManagerCheckOCSPResponse),
TEST_DECL(test_wolfSSL_CheckOCSPResponse),
TEST_DECL(test_wolfSSL_CertManagerLoadCABuffer),
TEST_DECL(test_wolfSSL_CertManagerGetCerts),
TEST_DECL(test_wolfSSL_CertManagerSetVerify),

View File

@ -34264,6 +34264,10 @@ static const ASNItem ocspBasicRespASN[] = {
/* SIGALGO */ { 1, ASN_SEQUENCE, 1, 1, 0, },
/* SIGALGO_OID */ { 2, ASN_OBJECT_ID, 0, 0, 0 },
/* SIGALGO_NULL */ { 2, ASN_TAG_NULL, 0, 0, 1 },
/* parameters */
#ifdef WC_RSA_PSS
/* SIGALGO_PARAMS */ { 2, ASN_SEQUENCE, 1, 0, 1 },
#endif
/* signature */
/* SIGNATURE */ { 1, ASN_BIT_STRING, 0, 0, 0 },
/* certs */
@ -34276,6 +34280,9 @@ enum {
OCSPBASICRESPASN_IDX_SIGALGO,
OCSPBASICRESPASN_IDX_SIGALGO_OID,
OCSPBASICRESPASN_IDX_SIGALGO_NULL,
#ifdef WC_RSA_PSS
OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS,
#endif
OCSPBASICRESPASN_IDX_SIGNATURE,
OCSPBASICRESPASN_IDX_CERTS,
OCSPBASICRESPASN_IDX_CERTS_SEQ,
@ -34291,9 +34298,13 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
#ifndef WOLFSSL_ASN_TEMPLATE
int length;
word32 idx = *ioIndex;
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
word32 end_index;
#endif
int ret;
int sigLength;
const byte* sigParams = NULL;
word32 sigParamsSz = 0;
WOLFSSL_ENTER("DecodeBasicOcspResponse");
(void)heap;
@ -34303,14 +34314,34 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
if (idx + length > size)
return ASN_INPUT_E;
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
end_index = idx + length;
#endif
if ((ret = DecodeResponseData(source, &idx, resp, size)) < 0)
return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
/* Get the signature algorithm */
if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0)
if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0) {
return ASN_PARSE_E;
}
#ifdef WC_RSA_PSS
else if (resp->sigOID == CTC_RSASSAPSS) {
word32 sz;
int len;
const byte* params;
sz = idx;
params = source + idx;
if (GetSequence(source, &idx, &len, size) < 0)
ret = ASN_PARSE_E;
if (ret == 0) {
idx += len;
sigParams = params;
sigParamsSz = idx - sz;
}
}
#endif
ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL);
if (ret != 0)
@ -34378,7 +34409,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
&cert->sigCtx,
resp->response, resp->responseSz,
cert->publicKey, cert->pubKeySize, cert->keyOID,
resp->sig, resp->sigSz, resp->sigOID, NULL, 0, NULL);
resp->sig, resp->sigSz, resp->sigOID, sigParams, sigParamsSz,
NULL);
if (ret != 0) {
WOLFSSL_MSG("\tOCSP Confirm signature failed");
@ -34415,7 +34447,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
/* ConfirmSignature is blocking here */
sigValid = ConfirmSignature(&sigCtx, resp->response,
resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
resp->sig, resp->sigSz, resp->sigOID, NULL, 0, NULL);
resp->sig, resp->sigSz, resp->sigOID, sigParams, sigParamsSz,
NULL);
}
if (ca == NULL || sigValid != 0) {
WOLFSSL_MSG("\tOCSP Confirm signature failed");
@ -34431,6 +34464,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
DECL_ASNGETDATA(dataASN, ocspBasicRespASN_Length);
int ret = 0;
word32 idx = *ioIndex;
const byte* sigParams = NULL;
word32 sigParamsSz = 0;
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* cert = NULL;
@ -34463,6 +34498,16 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
ret = ASN_PARSE_E;
}
}
#ifdef WC_RSA_PSS
if (ret == 0 && (dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS].tag != 0)) {
sigParams = GetASNItem_Addr(
dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
source);
sigParamsSz =
GetASNItem_Length(dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
source);
}
#endif
if (ret == 0) {
/* Get the signature OID and signature. */
resp->sigOID = dataASN[OCSPBASICRESPASN_IDX_SIGALGO_OID].data.oid.sum;
@ -34535,7 +34580,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
/* Check the signature of the response CA public key. */
sigValid = ConfirmSignature(&sigCtx, resp->response,
resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
resp->sig, resp->sigSz, resp->sigOID, NULL, 0, NULL);
resp->sig, resp->sigSz, resp->sigOID, sigParams, sigParamsSz,
NULL);
}
if ((ca == NULL) || (sigValid != 0)) {
/* Didn't find certificate or signature verificate failed. */