forked from wolfSSL/wolfssl
adds contingence plan (force OCSP check when the server answer the status_request extension but doesn't sends a CertificateStatus message);
adds back status_request to context level;
This commit is contained in:
@@ -983,10 +983,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
||||
if (statusRequest)
|
||||
if (statusRequest) {
|
||||
if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP)
|
||||
!= SSL_SUCCESS)
|
||||
err_sys("UseCertificateStatusRequest failed");
|
||||
|
||||
wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
|
||||
}
|
||||
#endif
|
||||
|
||||
tcp_connect(&sockfd, host, port, doDTLS, ssl);
|
||||
|
@@ -4451,15 +4451,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
||||
|
||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
||||
if (ssl->options.side == WOLFSSL_CLIENT_END) {
|
||||
switch (ssl->status_request) {
|
||||
case WOLFSSL_CSR_OCSP: {
|
||||
OcspRequest* request =
|
||||
TLSX_CSR_GetRequest(ssl->extensions);
|
||||
|
||||
fatal = InitOcspRequest(request, dCert, 0, NULL, 0);
|
||||
doLookup = 0;
|
||||
}
|
||||
break;
|
||||
if (ssl->status_request) {
|
||||
fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert);
|
||||
doLookup = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -5112,8 +5106,11 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
|
||||
if (ssl->msgsReceived.got_certificate_status == 0) {
|
||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
||||
if (ssl->status_request) {
|
||||
int ret;
|
||||
|
||||
WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
|
||||
return OUT_OF_ORDER_E;
|
||||
if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -8736,14 +8733,17 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
|
||||
case RSA_SIGN_FAULT:
|
||||
return "RSA Signature Fault Error";
|
||||
|
||||
case HANDSHAKE_SIZE_ERROR:
|
||||
return "Handshake message too large Error";
|
||||
|
||||
case UNKNOWN_ALPN_PROTOCOL_NAME_E:
|
||||
return "Unrecognized protocol name Error";
|
||||
|
||||
case BAD_CERTIFICATE_STATUS_ERROR:
|
||||
return "Bad Certificate Status Message Error";
|
||||
|
||||
case HANDSHAKE_SIZE_ERROR:
|
||||
return "Handshake message too large Error";
|
||||
case OCSP_INVALID_STATUS:
|
||||
return "Invalid OCSP Status Error";
|
||||
|
||||
default :
|
||||
return "unknown error number";
|
||||
|
299
src/ocsp.c
299
src/ocsp.c
@@ -34,59 +34,68 @@
|
||||
#include <wolfssl/ocsp.h>
|
||||
#include <wolfssl/internal.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
|
||||
int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
|
||||
{
|
||||
WOLFSSL_ENTER("InitOCSP");
|
||||
XMEMSET(ocsp, 0, sizeof(*ocsp));
|
||||
ocsp->cm = cm;
|
||||
|
||||
ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
|
||||
|
||||
if (InitMutex(&ocsp->ocspLock) != 0)
|
||||
return BAD_MUTEX_E;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
|
||||
{
|
||||
WOLFSSL_ENTER("InitOCSP_Entry");
|
||||
|
||||
XMEMSET(ocspe, 0, sizeof(*ocspe));
|
||||
XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
|
||||
XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
|
||||
ocsp->cm = cm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void FreeOCSP_Entry(OCSP_Entry* ocspe)
|
||||
static int InitOcspEntry(OcspEntry* entry, OcspRequest* request)
|
||||
{
|
||||
CertStatus* tmp = ocspe->status;
|
||||
WOLFSSL_ENTER("InitOcspEntry");
|
||||
|
||||
WOLFSSL_ENTER("FreeOCSP_Entry");
|
||||
ForceZero(entry, sizeof(OcspEntry));
|
||||
|
||||
while (tmp) {
|
||||
CertStatus* next = tmp->next;
|
||||
XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
|
||||
tmp = next;
|
||||
XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE);
|
||||
XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void FreeOcspEntry(OcspEntry* entry)
|
||||
{
|
||||
CertStatus *status, *next;
|
||||
|
||||
WOLFSSL_ENTER("FreeOcspEntry");
|
||||
|
||||
for (status = entry->status; status; status = next) {
|
||||
next = status->next;
|
||||
XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
|
||||
{
|
||||
OCSP_Entry* tmp = ocsp->ocspList;
|
||||
OcspEntry *entry, *next;
|
||||
|
||||
WOLFSSL_ENTER("FreeOCSP");
|
||||
|
||||
while (tmp) {
|
||||
OCSP_Entry* next = tmp->next;
|
||||
FreeOCSP_Entry(tmp);
|
||||
XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
||||
tmp = next;
|
||||
for (entry = ocsp->ocspList; entry; entry = next) {
|
||||
next = entry->next;
|
||||
FreeOcspEntry(entry);
|
||||
XFREE(entry, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
||||
}
|
||||
|
||||
FreeMutex(&ocsp->ocspLock);
|
||||
|
||||
if (dynamic)
|
||||
XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP);
|
||||
}
|
||||
@@ -107,84 +116,135 @@ static int xstat2err(int stat)
|
||||
|
||||
int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
|
||||
{
|
||||
byte* ocspReqBuf = NULL;
|
||||
int ocspReqSz = 2048;
|
||||
byte* ocspRespBuf = NULL;
|
||||
int result = -1;
|
||||
OCSP_Entry* ocspe;
|
||||
CertStatus* certStatus = NULL;
|
||||
const char *url;
|
||||
int urlSz;
|
||||
int ret = OCSP_LOOKUP_FAIL;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
CertStatus* newStatus;
|
||||
OcspRequest* ocspRequest;
|
||||
OcspResponse* ocspResponse;
|
||||
#else
|
||||
CertStatus newStatus[1];
|
||||
OcspRequest ocspRequest[1];
|
||||
OcspResponse ocspResponse[1];
|
||||
#endif
|
||||
|
||||
WOLFSSL_ENTER("CheckCertOCSP");
|
||||
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ocspRequest == NULL) {
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce) == 0) {
|
||||
ret = CheckOcspRequest(ocsp, ocspRequest);
|
||||
|
||||
FreeOcspRequest(ocspRequest);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
|
||||
OcspEntry** entry)
|
||||
{
|
||||
WOLFSSL_ENTER("GetOcspEntry");
|
||||
|
||||
*entry = NULL;
|
||||
|
||||
if (LockMutex(&ocsp->ocspLock) != 0) {
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
|
||||
ocspe = ocsp->ocspList;
|
||||
while (ocspe) {
|
||||
if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
|
||||
&& XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
|
||||
SHA_DIGEST_SIZE) == 0)
|
||||
for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
|
||||
if (XMEMCMP((*entry)->issuerHash, request->issuerHash,
|
||||
OCSP_DIGEST_SIZE) == 0
|
||||
&& XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
|
||||
OCSP_DIGEST_SIZE) == 0)
|
||||
break;
|
||||
else
|
||||
ocspe = ocspe->next;
|
||||
}
|
||||
|
||||
if (ocspe == NULL) {
|
||||
ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
|
||||
NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
||||
if (ocspe != NULL) {
|
||||
InitOCSP_Entry(ocspe, cert);
|
||||
ocspe->next = ocsp->ocspList;
|
||||
ocsp->ocspList = ocspe;
|
||||
}
|
||||
else {
|
||||
UnLockMutex(&ocsp->ocspLock);
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
|
||||
return MEMORY_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
certStatus = ocspe->status;
|
||||
while (certStatus) {
|
||||
if (certStatus->serialSz == cert->serialSz &&
|
||||
XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
|
||||
break;
|
||||
else
|
||||
certStatus = certStatus->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (certStatus != NULL) {
|
||||
if (!ValidateDate(certStatus->thisDate,
|
||||
certStatus->thisDateFormat, BEFORE) ||
|
||||
(certStatus->nextDate[0] == 0) ||
|
||||
!ValidateDate(certStatus->nextDate,
|
||||
certStatus->nextDateFormat, AFTER)) {
|
||||
WOLFSSL_MSG("\tinvalid status date, looking up cert");
|
||||
}
|
||||
else {
|
||||
result = xstat2err(certStatus->status);
|
||||
UnLockMutex(&ocsp->ocspLock);
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", result);
|
||||
return result;
|
||||
if (*entry == NULL) {
|
||||
*entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
|
||||
NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
||||
if (*entry) {
|
||||
InitOcspEntry(*entry, request);
|
||||
(*entry)->next = ocsp->ocspList;
|
||||
ocsp->ocspList = *entry;
|
||||
}
|
||||
}
|
||||
|
||||
UnLockMutex(&ocsp->ocspLock);
|
||||
|
||||
return *entry ? 0 : MEMORY_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
|
||||
OcspEntry* entry, CertStatus** status)
|
||||
{
|
||||
int ret = OCSP_INVALID_STATUS;
|
||||
|
||||
WOLFSSL_ENTER("GetOcspStatus");
|
||||
|
||||
*status = NULL;
|
||||
|
||||
if (LockMutex(&ocsp->ocspLock) != 0) {
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
|
||||
for (*status = entry->status; *status; *status = (*status)->next)
|
||||
if ((*status)->serialSz == request->serialSz
|
||||
&& !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
|
||||
break;
|
||||
|
||||
if (*status) {
|
||||
if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE)
|
||||
&& ((*status)->nextDate[0] != 0)
|
||||
&& ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER))
|
||||
ret = xstat2err((*status)->status);
|
||||
}
|
||||
|
||||
UnLockMutex(&ocsp->ocspLock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest)
|
||||
{
|
||||
OcspEntry* entry = NULL;
|
||||
CertStatus* status = NULL;
|
||||
byte* request = NULL;
|
||||
int requestSz = 2048;
|
||||
byte* response = NULL;
|
||||
const char* url;
|
||||
int urlSz;
|
||||
int ret = -1;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
CertStatus* newStatus;
|
||||
OcspResponse* ocspResponse;
|
||||
#else
|
||||
CertStatus newStatus[1];
|
||||
OcspResponse ocspResponse[1];
|
||||
#endif
|
||||
|
||||
WOLFSSL_ENTER("CheckOcspRequest");
|
||||
|
||||
ret = GetOcspEntry(ocsp, ocspRequest, &entry);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = GetOcspStatus(ocsp, ocspRequest, entry, &status);
|
||||
if (ret != OCSP_INVALID_STATUS)
|
||||
return ret;
|
||||
|
||||
if (ocsp->cm->ocspUseOverrideURL) {
|
||||
url = ocsp->cm->ocspOverrideURL;
|
||||
if (url != NULL && url[0] != '\0')
|
||||
@@ -192,17 +252,17 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
|
||||
else
|
||||
return OCSP_NEED_URL;
|
||||
}
|
||||
else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
|
||||
url = (const char *)cert->extAuthInfo;
|
||||
urlSz = cert->extAuthInfoSz;
|
||||
else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
|
||||
url = (const char *)ocspRequest->url;
|
||||
urlSz = ocspRequest->urlSz;
|
||||
}
|
||||
else {
|
||||
/* cert doesn't have extAuthInfo, assuming CERT_GOOD */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
|
||||
if (ocspReqBuf == NULL) {
|
||||
request = (byte*)XMALLOC(requestSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
|
||||
if (request == NULL) {
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
|
||||
return MEMORY_ERROR;
|
||||
}
|
||||
@@ -210,60 +270,53 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) {
|
||||
if (newStatus == NULL || ocspResponse == NULL) {
|
||||
if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ocspRequest) XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(request, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
result = InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
|
||||
ocspReqBuf, ocspReqSz);
|
||||
if (result == 0) {
|
||||
ocspReqSz = EncodeOcspRequest(ocspRequest);
|
||||
requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
|
||||
|
||||
if (ocsp->cm->ocspIOCb)
|
||||
result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
|
||||
ocspReqBuf, ocspReqSz, &ocspRespBuf);
|
||||
}
|
||||
if (ocsp->cm->ocspIOCb)
|
||||
ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
|
||||
request, requestSz, &response);
|
||||
|
||||
if (result >= 0 && ocspRespBuf) {
|
||||
if (ret >= 0 && response) {
|
||||
XMEMSET(newStatus, 0, sizeof(CertStatus));
|
||||
|
||||
InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result);
|
||||
InitOcspResponse(ocspResponse, newStatus, response, ret);
|
||||
OcspResponseDecode(ocspResponse);
|
||||
|
||||
if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
|
||||
result = OCSP_LOOKUP_FAIL;
|
||||
ret = OCSP_LOOKUP_FAIL;
|
||||
else {
|
||||
if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
|
||||
result = xstat2err(ocspResponse->status->status);
|
||||
ret = xstat2err(ocspResponse->status->status);
|
||||
|
||||
if (LockMutex(&ocsp->ocspLock) != 0)
|
||||
result = BAD_MUTEX_E;
|
||||
ret = BAD_MUTEX_E;
|
||||
else {
|
||||
if (certStatus != NULL)
|
||||
if (status != NULL)
|
||||
/* Replace existing certificate entry with updated */
|
||||
XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
|
||||
XMEMCPY(status, newStatus, sizeof(CertStatus));
|
||||
else {
|
||||
/* Save new certificate entry */
|
||||
certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
|
||||
status = (CertStatus*)XMALLOC(sizeof(CertStatus),
|
||||
NULL, DYNAMIC_TYPE_OCSP_STATUS);
|
||||
if (certStatus != NULL) {
|
||||
XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
|
||||
certStatus->next = ocspe->status;
|
||||
ocspe->status = certStatus;
|
||||
ocspe->totalStatus++;
|
||||
if (status != NULL) {
|
||||
XMEMCPY(status, newStatus, sizeof(CertStatus));
|
||||
status->next = entry->status;
|
||||
entry->status = status;
|
||||
entry->totalStatus++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,26 +324,22 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
|
||||
}
|
||||
}
|
||||
else
|
||||
result = OCSP_LOOKUP_FAIL;
|
||||
ret = OCSP_LOOKUP_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = OCSP_LOOKUP_FAIL;
|
||||
|
||||
FreeOcspRequest(ocspRequest);
|
||||
XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
|
||||
ret = OCSP_LOOKUP_FAIL;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
|
||||
ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);
|
||||
if (response != NULL && ocsp->cm->ocspRespFreeCb)
|
||||
ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response);
|
||||
|
||||
WOLFSSL_LEAVE("CheckCertOCSP", result);
|
||||
return result;
|
||||
WOLFSSL_LEAVE("CheckOcspRequest", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -804,6 +804,15 @@ int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type)
|
||||
return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type);
|
||||
}
|
||||
|
||||
|
||||
int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type)
|
||||
{
|
||||
if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type);
|
||||
}
|
||||
|
||||
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
|
||||
|
||||
/* Elliptic Curves */
|
||||
|
77
src/tls.c
77
src/tls.c
@@ -1900,7 +1900,7 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr)
|
||||
{
|
||||
switch (csr->status_type) {
|
||||
case WOLFSSL_CSR_OCSP:
|
||||
FreeOcspRequest(&csr->data.ocspRequest);
|
||||
FreeOcspRequest(&csr->request.ocsp);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1959,6 +1959,8 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
|
||||
static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
byte isRequest)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* shut up compiler warnings */
|
||||
(void) ssl; (void) input;
|
||||
|
||||
@@ -1967,15 +1969,43 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
|
||||
CertificateStatusRequest* csr = extension ? extension->data : NULL;
|
||||
|
||||
if (csr == NULL)
|
||||
return BUFFER_ERROR; /* unexpected extension */
|
||||
if (!csr) {
|
||||
/* look at context level */
|
||||
|
||||
ssl->status_request = csr->status_type;
|
||||
extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST);
|
||||
csr = extension ? extension->data : NULL;
|
||||
|
||||
if (!csr)
|
||||
return BUFFER_ERROR; /* unexpected extension */
|
||||
|
||||
/* enable extension at ssl level */
|
||||
ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
||||
csr->status_type);
|
||||
if (ret != SSL_SUCCESS)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssl->status_request = 1;
|
||||
|
||||
return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
|
||||
CertificateStatusRequest* csr = extension ? extension->data : NULL;
|
||||
|
||||
if (csr) {
|
||||
switch (csr->status_type) {
|
||||
case WOLFSSL_CSR_OCSP:
|
||||
return InitOcspRequest(&csr->request.ocsp, cert, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1987,7 +2017,7 @@ void* TLSX_CSR_GetRequest(TLSX* extensions)
|
||||
if (csr) {
|
||||
switch (csr->status_type) {
|
||||
case WOLFSSL_CSR_OCSP:
|
||||
return &csr->data.ocspRequest;
|
||||
return &csr->request.ocsp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1995,31 +2025,42 @@ void* TLSX_CSR_GetRequest(TLSX* extensions)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
|
||||
CertificateStatusRequest* csr = extension ? extension->data : NULL;
|
||||
|
||||
if (csr) {
|
||||
switch (csr->status_type) {
|
||||
case WOLFSSL_CSR_OCSP:
|
||||
if (ssl->ctx->cm->ocspEnabled)
|
||||
return CheckOcspRequest(ssl->ctx->cm->ocsp,
|
||||
&csr->request.ocsp);
|
||||
else
|
||||
return OCSP_LOOKUP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type)
|
||||
{
|
||||
CertificateStatusRequest* csr = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!extensions)
|
||||
if (!extensions || status_type != WOLFSSL_CSR_OCSP)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
csr = (CertificateStatusRequest*)XMALLOC(sizeof(CertificateStatusRequest),
|
||||
NULL, DYNAMIC_TYPE_TLSX);
|
||||
csr = (CertificateStatusRequest*)
|
||||
XMALLOC(sizeof(CertificateStatusRequest), NULL, DYNAMIC_TYPE_TLSX);
|
||||
if (!csr)
|
||||
return MEMORY_E;
|
||||
|
||||
ForceZero(csr, sizeof(CertificateStatusRequest));
|
||||
|
||||
csr->status_type = status_type;
|
||||
|
||||
switch (status_type) {
|
||||
case WOLFSSL_CSR_OCSP:
|
||||
ForceZero(&csr->data.ocspRequest, sizeof(OcspRequest));
|
||||
break;
|
||||
|
||||
default:
|
||||
XFREE(csr, NULL, DYNAMIC_TYPE_TLSX);
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) {
|
||||
XFREE(csr, NULL, DYNAMIC_TYPE_TLSX);
|
||||
return ret;
|
||||
|
@@ -8839,7 +8839,7 @@ static word32 SetOcspReqExtensions(word32 extSz, byte* output,
|
||||
}
|
||||
|
||||
|
||||
int EncodeOcspRequest(OcspRequest* req)
|
||||
int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
|
||||
{
|
||||
byte seqArray[5][MAX_SEQ_SZ];
|
||||
/* The ASN.1 of the OCSP Request is an onion of sequences */
|
||||
@@ -8848,7 +8848,6 @@ int EncodeOcspRequest(OcspRequest* req)
|
||||
byte issuerKeyArray[MAX_ENCODED_DIG_SZ];
|
||||
byte snArray[MAX_SN_SZ];
|
||||
byte extArray[MAX_OCSP_EXT_SZ];
|
||||
byte* output = req->request;
|
||||
word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz;
|
||||
int i;
|
||||
|
||||
@@ -8865,21 +8864,9 @@ int EncodeOcspRequest(OcspRequest* req)
|
||||
snSz = SetSerialNumber(req->serial, req->serialSz, snArray);
|
||||
extSz = 0;
|
||||
|
||||
if (req->useNonce) {
|
||||
WC_RNG rng;
|
||||
if (wc_InitRng(&rng) != 0) {
|
||||
WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
|
||||
} else {
|
||||
if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
|
||||
WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
|
||||
else {
|
||||
req->nonceSz = MAX_OCSP_NONCE_SZ;
|
||||
extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
|
||||
if (req->nonceSz)
|
||||
extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
|
||||
req->nonce, req->nonceSz);
|
||||
}
|
||||
wc_FreeRng(&rng);
|
||||
}
|
||||
}
|
||||
|
||||
totalSz = algoSz + issuerSz + issuerKeySz + snSz;
|
||||
for (i = 4; i >= 0; i--) {
|
||||
@@ -8888,6 +8875,9 @@ int EncodeOcspRequest(OcspRequest* req)
|
||||
if (i == 2) totalSz += extSz;
|
||||
}
|
||||
|
||||
if (totalSz > size)
|
||||
return BUFFER_E;
|
||||
|
||||
totalSz = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
|
||||
@@ -8915,8 +8905,7 @@ int EncodeOcspRequest(OcspRequest* req)
|
||||
}
|
||||
|
||||
|
||||
int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
|
||||
byte* dest, word32 destSz)
|
||||
int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce)
|
||||
{
|
||||
WOLFSSL_ENTER("InitOcspRequest");
|
||||
|
||||
@@ -8929,17 +8918,42 @@ int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
|
||||
XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE);
|
||||
XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE);
|
||||
|
||||
req->serial = (byte*)XMALLOC(cert->serialSz, NULL, DYNAMIC_TYPE_OCSP);
|
||||
req->serial = (byte*)XMALLOC(cert->serialSz, NULL,
|
||||
DYNAMIC_TYPE_OCSP_REQUEST);
|
||||
if (req->serial == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
XMEMCPY(req->serial, cert->serial, cert->serialSz);
|
||||
req->serialSz = cert->serialSz;
|
||||
|
||||
if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
|
||||
req->url = (byte*)XMALLOC(cert->extAuthInfoSz, NULL,
|
||||
DYNAMIC_TYPE_OCSP_REQUEST);
|
||||
if (req->url == NULL) {
|
||||
XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP);
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz);
|
||||
req->urlSz = cert->extAuthInfoSz;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
req->useNonce = useNonce;
|
||||
req->request = dest;
|
||||
req->requestSz = destSz;
|
||||
if (useNonce) {
|
||||
WC_RNG rng;
|
||||
|
||||
if (wc_InitRng(&rng) != 0) {
|
||||
WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
|
||||
} else {
|
||||
if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
|
||||
WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
|
||||
else
|
||||
req->nonceSz = MAX_OCSP_NONCE_SZ;
|
||||
|
||||
wc_FreeRng(&rng);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -8948,8 +8962,13 @@ void FreeOcspRequest(OcspRequest* req)
|
||||
{
|
||||
WOLFSSL_ENTER("FreeOcspRequest");
|
||||
|
||||
if (req && req->serial)
|
||||
XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP);
|
||||
if (req) {
|
||||
if (req->serial)
|
||||
XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
|
||||
|
||||
if (req->url)
|
||||
XFREE(req->url, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8973,7 +8992,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
|
||||
|
||||
/* Nonces are not critical. The responder may not necessarily add
|
||||
* the nonce to the response. */
|
||||
if (req->useNonce && resp->nonceSz != 0) {
|
||||
if (req->nonceSz && resp->nonceSz != 0) {
|
||||
cmp = req->nonceSz - resp->nonceSz;
|
||||
if (cmp != 0)
|
||||
{
|
||||
|
@@ -140,6 +140,7 @@ enum wolfSSL_ErrorCodes {
|
||||
|
||||
UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/
|
||||
BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */
|
||||
OCSP_INVALID_STATUS = -407, /* Invalid OCSP Status */
|
||||
|
||||
/* add strings to SetErrorString !!!!! */
|
||||
|
||||
|
@@ -1255,7 +1255,7 @@ struct WOLFSSL_CIPHER {
|
||||
};
|
||||
|
||||
|
||||
typedef struct OCSP_Entry OCSP_Entry;
|
||||
typedef struct OcspEntry OcspEntry;
|
||||
|
||||
#ifdef NO_SHA
|
||||
#define OCSP_DIGEST_SIZE SHA256_DIGEST_SIZE
|
||||
@@ -1268,12 +1268,12 @@ typedef struct OCSP_Entry OCSP_Entry;
|
||||
typedef struct CertStatus CertStatus;
|
||||
#endif
|
||||
|
||||
struct OCSP_Entry {
|
||||
OCSP_Entry* next; /* next entry */
|
||||
byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */
|
||||
byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */
|
||||
CertStatus* status; /* OCSP response list */
|
||||
int totalStatus; /* number on list */
|
||||
struct OcspEntry {
|
||||
OcspEntry* next; /* next entry */
|
||||
byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */
|
||||
byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */
|
||||
CertStatus* status; /* OCSP response list */
|
||||
int totalStatus; /* number on list */
|
||||
};
|
||||
|
||||
|
||||
@@ -1284,7 +1284,7 @@ struct OCSP_Entry {
|
||||
/* wolfSSL OCSP controller */
|
||||
struct WOLFSSL_OCSP {
|
||||
WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */
|
||||
OCSP_Entry* ocspList; /* OCSP response list */
|
||||
OcspEntry* ocspList; /* OCSP response list */
|
||||
wolfSSL_Mutex ocspLock; /* OCSP list lock */
|
||||
};
|
||||
|
||||
@@ -1577,14 +1577,15 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions);
|
||||
typedef struct {
|
||||
byte status_type;
|
||||
union {
|
||||
OcspRequest ocspRequest;
|
||||
} data;
|
||||
OcspRequest ocsp;
|
||||
} request;
|
||||
} CertificateStatusRequest;
|
||||
|
||||
WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions,
|
||||
WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions,
|
||||
byte status_type);
|
||||
WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
|
||||
|
||||
WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert);
|
||||
WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
|
||||
WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl);
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -40,6 +40,8 @@ WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*);
|
||||
WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic);
|
||||
|
||||
WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*);
|
||||
WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp,
|
||||
OcspRequest* ocspRequest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@@ -1419,6 +1419,9 @@ enum {
|
||||
WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl,
|
||||
unsigned char status_type);
|
||||
|
||||
WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx,
|
||||
unsigned char status_type);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@@ -709,25 +709,22 @@ struct OcspResponse {
|
||||
struct OcspRequest {
|
||||
byte issuerHash[KEYID_SIZE];
|
||||
byte issuerKeyHash[KEYID_SIZE];
|
||||
byte* serial; /* copy of the serial number in source cert; OWNED */
|
||||
byte* serial; /* copy of the serial number in source cert */
|
||||
int serialSz;
|
||||
byte* url; /* copy of the extAuthInfo in source cert */
|
||||
int urlSz;
|
||||
|
||||
byte nonce[MAX_OCSP_NONCE_SZ];
|
||||
int nonceSz;
|
||||
byte useNonce;
|
||||
|
||||
byte* request; /* pointer to the destination ASN.1 buffer; NOT OWNED */
|
||||
word32 requestSz; /* length of the destination buffer */
|
||||
byte nonce[MAX_OCSP_NONCE_SZ];
|
||||
int nonceSz;
|
||||
};
|
||||
|
||||
|
||||
WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32);
|
||||
WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*);
|
||||
|
||||
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*,
|
||||
byte, byte*, word32);
|
||||
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte);
|
||||
WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*);
|
||||
WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*);
|
||||
WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32);
|
||||
|
||||
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*);
|
||||
|
||||
|
@@ -286,7 +286,8 @@
|
||||
DYNAMIC_TYPE_SIGNATURE = 45,
|
||||
DYNAMIC_TYPE_HASHES = 46,
|
||||
DYNAMIC_TYPE_SRP = 47,
|
||||
DYNAMIC_TYPE_COOKIE_PWD = 48
|
||||
DYNAMIC_TYPE_COOKIE_PWD = 48,
|
||||
DYNAMIC_TYPE_OCSP_REQUEST = 49,
|
||||
};
|
||||
|
||||
/* max error buffer string size */
|
||||
|
Reference in New Issue
Block a user