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:
Moisés Guimarães
2015-10-25 21:21:41 -03:00
parent 42380793c9
commit 14fa980dad
12 changed files with 332 additions and 206 deletions

View File

@@ -983,10 +983,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
} }
#endif #endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (statusRequest) if (statusRequest) {
if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP) if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP)
!= SSL_SUCCESS) != SSL_SUCCESS)
err_sys("UseCertificateStatusRequest failed"); err_sys("UseCertificateStatusRequest failed");
wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
}
#endif #endif
tcp_connect(&sockfd, host, port, doDTLS, ssl); tcp_connect(&sockfd, host, port, doDTLS, ssl);

View File

@@ -4451,16 +4451,10 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->options.side == WOLFSSL_CLIENT_END) { if (ssl->options.side == WOLFSSL_CLIENT_END) {
switch (ssl->status_request) { if (ssl->status_request) {
case WOLFSSL_CSR_OCSP: { fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert);
OcspRequest* request =
TLSX_CSR_GetRequest(ssl->extensions);
fatal = InitOcspRequest(request, dCert, 0, NULL, 0);
doLookup = 0; doLookup = 0;
} }
break;
}
} }
#endif #endif
@@ -5112,8 +5106,11 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
if (ssl->msgsReceived.got_certificate_status == 0) { if (ssl->msgsReceived.got_certificate_status == 0) {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->status_request) { if (ssl->status_request) {
int ret;
WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
return OUT_OF_ORDER_E; if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
return ret;
} }
#endif #endif
} }
@@ -8736,14 +8733,17 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case RSA_SIGN_FAULT: case RSA_SIGN_FAULT:
return "RSA Signature Fault Error"; return "RSA Signature Fault Error";
case HANDSHAKE_SIZE_ERROR:
return "Handshake message too large Error";
case UNKNOWN_ALPN_PROTOCOL_NAME_E: case UNKNOWN_ALPN_PROTOCOL_NAME_E:
return "Unrecognized protocol name Error"; return "Unrecognized protocol name Error";
case BAD_CERTIFICATE_STATUS_ERROR: case BAD_CERTIFICATE_STATUS_ERROR:
return "Bad Certificate Status Message Error"; return "Bad Certificate Status Message Error";
case HANDSHAKE_SIZE_ERROR: case OCSP_INVALID_STATUS:
return "Handshake message too large Error"; return "Invalid OCSP Status Error";
default : default :
return "unknown error number"; return "unknown error number";

View File

@@ -34,59 +34,68 @@
#include <wolfssl/ocsp.h> #include <wolfssl/ocsp.h>
#include <wolfssl/internal.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) int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
{ {
WOLFSSL_ENTER("InitOCSP"); WOLFSSL_ENTER("InitOCSP");
XMEMSET(ocsp, 0, sizeof(*ocsp));
ocsp->cm = cm; ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
if (InitMutex(&ocsp->ocspLock) != 0) if (InitMutex(&ocsp->ocspLock) != 0)
return BAD_MUTEX_E; return BAD_MUTEX_E;
return 0; ocsp->cm = cm;
}
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);
return 0; 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) { XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE);
CertStatus* next = tmp->next; XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
tmp = next; 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) void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
{ {
OCSP_Entry* tmp = ocsp->ocspList; OcspEntry *entry, *next;
WOLFSSL_ENTER("FreeOCSP"); WOLFSSL_ENTER("FreeOCSP");
while (tmp) { for (entry = ocsp->ocspList; entry; entry = next) {
OCSP_Entry* next = tmp->next; next = entry->next;
FreeOCSP_Entry(tmp); FreeOcspEntry(entry);
XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY); XFREE(entry, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
tmp = next;
} }
FreeMutex(&ocsp->ocspLock); FreeMutex(&ocsp->ocspLock);
if (dynamic) if (dynamic)
XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP); XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP);
} }
@@ -107,84 +116,135 @@ static int xstat2err(int stat)
int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
{ {
byte* ocspReqBuf = NULL; int ret = OCSP_LOOKUP_FAIL;
int ocspReqSz = 2048;
byte* ocspRespBuf = NULL;
int result = -1;
OCSP_Entry* ocspe;
CertStatus* certStatus = NULL;
const char *url;
int urlSz;
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
CertStatus* newStatus;
OcspRequest* ocspRequest; OcspRequest* ocspRequest;
OcspResponse* ocspResponse;
#else #else
CertStatus newStatus[1];
OcspRequest ocspRequest[1]; OcspRequest ocspRequest[1];
OcspResponse ocspResponse[1];
#endif #endif
WOLFSSL_ENTER("CheckCertOCSP"); 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) { if (LockMutex(&ocsp->ocspLock) != 0) {
WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
return BAD_MUTEX_E; return BAD_MUTEX_E;
} }
ocspe = ocsp->ocspList; for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
while (ocspe) { if (XMEMCMP((*entry)->issuerHash, request->issuerHash,
if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0 OCSP_DIGEST_SIZE) == 0
&& XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash, && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
SHA_DIGEST_SIZE) == 0) OCSP_DIGEST_SIZE) == 0)
break; break;
else
ocspe = ocspe->next;
}
if (ocspe == NULL) { if (*entry == NULL) {
ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry), *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
NULL, DYNAMIC_TYPE_OCSP_ENTRY); NULL, DYNAMIC_TYPE_OCSP_ENTRY);
if (ocspe != NULL) { if (*entry) {
InitOCSP_Entry(ocspe, cert); InitOcspEntry(*entry, request);
ocspe->next = ocsp->ocspList; (*entry)->next = ocsp->ocspList;
ocsp->ocspList = ocspe; ocsp->ocspList = *entry;
} }
else { }
UnLockMutex(&ocsp->ocspLock); UnLockMutex(&ocsp->ocspLock);
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
return MEMORY_ERROR; 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;
} }
}
else { for (*status = entry->status; *status; *status = (*status)->next)
certStatus = ocspe->status; if ((*status)->serialSz == request->serialSz
while (certStatus) { && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
if (certStatus->serialSz == cert->serialSz &&
XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
break; break;
else
certStatus = certStatus->next;
}
}
if (certStatus != NULL) { if (*status) {
if (!ValidateDate(certStatus->thisDate, if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE)
certStatus->thisDateFormat, BEFORE) || && ((*status)->nextDate[0] != 0)
(certStatus->nextDate[0] == 0) || && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER))
!ValidateDate(certStatus->nextDate, ret = xstat2err((*status)->status);
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;
}
} }
UnLockMutex(&ocsp->ocspLock); 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) { if (ocsp->cm->ocspUseOverrideURL) {
url = ocsp->cm->ocspOverrideURL; url = ocsp->cm->ocspOverrideURL;
if (url != NULL && url[0] != '\0') if (url != NULL && url[0] != '\0')
@@ -192,17 +252,17 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
else else
return OCSP_NEED_URL; return OCSP_NEED_URL;
} }
else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) { else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
url = (const char *)cert->extAuthInfo; url = (const char *)ocspRequest->url;
urlSz = cert->extAuthInfoSz; urlSz = ocspRequest->urlSz;
} }
else { else {
/* cert doesn't have extAuthInfo, assuming CERT_GOOD */ /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
return 0; return 0;
} }
ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER); request = (byte*)XMALLOC(requestSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
if (ocspReqBuf == NULL) { if (request == NULL) {
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
return MEMORY_ERROR; return MEMORY_ERROR;
} }
@@ -210,60 +270,53 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
DYNAMIC_TYPE_TMP_BUFFER); 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 (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); 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); WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
return MEMORY_E; return MEMORY_E;
} }
#endif #endif
result = InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
ocspReqBuf, ocspReqSz);
if (result == 0) {
ocspReqSz = EncodeOcspRequest(ocspRequest);
if (ocsp->cm->ocspIOCb) if (ocsp->cm->ocspIOCb)
result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
ocspReqBuf, ocspReqSz, &ocspRespBuf); request, requestSz, &response);
}
if (result >= 0 && ocspRespBuf) { if (ret >= 0 && response) {
XMEMSET(newStatus, 0, sizeof(CertStatus)); XMEMSET(newStatus, 0, sizeof(CertStatus));
InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result); InitOcspResponse(ocspResponse, newStatus, response, ret);
OcspResponseDecode(ocspResponse); OcspResponseDecode(ocspResponse);
if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
result = OCSP_LOOKUP_FAIL; ret = OCSP_LOOKUP_FAIL;
else { else {
if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
result = xstat2err(ocspResponse->status->status); ret = xstat2err(ocspResponse->status->status);
if (LockMutex(&ocsp->ocspLock) != 0) if (LockMutex(&ocsp->ocspLock) != 0)
result = BAD_MUTEX_E; ret = BAD_MUTEX_E;
else { else {
if (certStatus != NULL) if (status != NULL)
/* Replace existing certificate entry with updated */ /* Replace existing certificate entry with updated */
XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); XMEMCPY(status, newStatus, sizeof(CertStatus));
else { else {
/* Save new certificate entry */ /* Save new certificate entry */
certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), status = (CertStatus*)XMALLOC(sizeof(CertStatus),
NULL, DYNAMIC_TYPE_OCSP_STATUS); NULL, DYNAMIC_TYPE_OCSP_STATUS);
if (certStatus != NULL) { if (status != NULL) {
XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); XMEMCPY(status, newStatus, sizeof(CertStatus));
certStatus->next = ocspe->status; status->next = entry->status;
ocspe->status = certStatus; entry->status = status;
ocspe->totalStatus++; entry->totalStatus++;
} }
} }
@@ -271,26 +324,22 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
} }
} }
else else
result = OCSP_LOOKUP_FAIL; ret = OCSP_LOOKUP_FAIL;
} }
} }
else else
result = OCSP_LOOKUP_FAIL; ret = OCSP_LOOKUP_FAIL;
FreeOcspRequest(ocspRequest);
XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif #endif
if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb) if (response != NULL && ocsp->cm->ocspRespFreeCb)
ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf); ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response);
WOLFSSL_LEAVE("CheckCertOCSP", result); WOLFSSL_LEAVE("CheckOcspRequest", ret);
return result; return ret;
} }

View File

@@ -804,6 +804,15 @@ int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type)
return TLSX_UseCertificateStatusRequest(&ssl->extensions, 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 */ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
/* Elliptic Curves */ /* Elliptic Curves */

View File

@@ -1900,7 +1900,7 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr)
{ {
switch (csr->status_type) { switch (csr->status_type) {
case WOLFSSL_CSR_OCSP: case WOLFSSL_CSR_OCSP:
FreeOcspRequest(&csr->data.ocspRequest); FreeOcspRequest(&csr->request.ocsp);
break; 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, static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
byte isRequest) byte isRequest)
{ {
int ret = 0;
/* shut up compiler warnings */ /* shut up compiler warnings */
(void) ssl; (void) input; (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); TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
CertificateStatusRequest* csr = extension ? extension->data : NULL; CertificateStatusRequest* csr = extension ? extension->data : NULL;
if (csr == NULL) if (!csr) {
/* look at context level */
extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST);
csr = extension ? extension->data : NULL;
if (!csr)
return BUFFER_ERROR; /* unexpected extension */ return BUFFER_ERROR; /* unexpected extension */
ssl->status_request = csr->status_type; /* 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. */ return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */
#endif #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; return 0;
} }
@@ -1987,7 +2017,7 @@ void* TLSX_CSR_GetRequest(TLSX* extensions)
if (csr) { if (csr) {
switch (csr->status_type) { switch (csr->status_type) {
case WOLFSSL_CSR_OCSP: case WOLFSSL_CSR_OCSP:
return &csr->data.ocspRequest; return &csr->request.ocsp;
break; break;
} }
} }
@@ -1995,31 +2025,42 @@ void* TLSX_CSR_GetRequest(TLSX* extensions)
return NULL; 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) int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type)
{ {
CertificateStatusRequest* csr = NULL; CertificateStatusRequest* csr = NULL;
int ret = 0; int ret = 0;
if (!extensions) if (!extensions || status_type != WOLFSSL_CSR_OCSP)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
csr = (CertificateStatusRequest*)XMALLOC(sizeof(CertificateStatusRequest), csr = (CertificateStatusRequest*)
NULL, DYNAMIC_TYPE_TLSX); XMALLOC(sizeof(CertificateStatusRequest), NULL, DYNAMIC_TYPE_TLSX);
if (!csr) if (!csr)
return MEMORY_E; return MEMORY_E;
ForceZero(csr, sizeof(CertificateStatusRequest));
csr->status_type = status_type; 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) { if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) {
XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); XFREE(csr, NULL, DYNAMIC_TYPE_TLSX);
return ret; return ret;

View File

@@ -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]; byte seqArray[5][MAX_SEQ_SZ];
/* The ASN.1 of the OCSP Request is an onion of sequences */ /* 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 issuerKeyArray[MAX_ENCODED_DIG_SZ];
byte snArray[MAX_SN_SZ]; byte snArray[MAX_SN_SZ];
byte extArray[MAX_OCSP_EXT_SZ]; byte extArray[MAX_OCSP_EXT_SZ];
byte* output = req->request;
word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz; word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz;
int i; int i;
@@ -8865,21 +8864,9 @@ int EncodeOcspRequest(OcspRequest* req)
snSz = SetSerialNumber(req->serial, req->serialSz, snArray); snSz = SetSerialNumber(req->serial, req->serialSz, snArray);
extSz = 0; extSz = 0;
if (req->useNonce) { if (req->nonceSz)
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, extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
req->nonce, req->nonceSz); req->nonce, req->nonceSz);
}
wc_FreeRng(&rng);
}
}
totalSz = algoSz + issuerSz + issuerKeySz + snSz; totalSz = algoSz + issuerSz + issuerKeySz + snSz;
for (i = 4; i >= 0; i--) { for (i = 4; i >= 0; i--) {
@@ -8888,6 +8875,9 @@ int EncodeOcspRequest(OcspRequest* req)
if (i == 2) totalSz += extSz; if (i == 2) totalSz += extSz;
} }
if (totalSz > size)
return BUFFER_E;
totalSz = 0; totalSz = 0;
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
XMEMCPY(output + totalSz, seqArray[i], seqSz[i]); XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
@@ -8915,8 +8905,7 @@ int EncodeOcspRequest(OcspRequest* req)
} }
int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce)
byte* dest, word32 destSz)
{ {
WOLFSSL_ENTER("InitOcspRequest"); WOLFSSL_ENTER("InitOcspRequest");
@@ -8929,17 +8918,42 @@ int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE); XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE);
XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, 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) if (req->serial == NULL)
return MEMORY_E; return MEMORY_E;
XMEMCPY(req->serial, cert->serial, cert->serialSz); XMEMCPY(req->serial, cert->serial, cert->serialSz);
req->serialSz = 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;
} }
req->useNonce = useNonce; XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz);
req->request = dest; req->urlSz = cert->extAuthInfoSz;
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; return 0;
} }
@@ -8948,8 +8962,13 @@ void FreeOcspRequest(OcspRequest* req)
{ {
WOLFSSL_ENTER("FreeOcspRequest"); WOLFSSL_ENTER("FreeOcspRequest");
if (req && req->serial) if (req) {
XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP); 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 /* Nonces are not critical. The responder may not necessarily add
* the nonce to the response. */ * the nonce to the response. */
if (req->useNonce && resp->nonceSz != 0) { if (req->nonceSz && resp->nonceSz != 0) {
cmp = req->nonceSz - resp->nonceSz; cmp = req->nonceSz - resp->nonceSz;
if (cmp != 0) if (cmp != 0)
{ {

View File

@@ -140,6 +140,7 @@ enum wolfSSL_ErrorCodes {
UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/ UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/
BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */ BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */
OCSP_INVALID_STATUS = -407, /* Invalid OCSP Status */
/* add strings to SetErrorString !!!!! */ /* add strings to SetErrorString !!!!! */

View File

@@ -1255,7 +1255,7 @@ struct WOLFSSL_CIPHER {
}; };
typedef struct OCSP_Entry OCSP_Entry; typedef struct OcspEntry OcspEntry;
#ifdef NO_SHA #ifdef NO_SHA
#define OCSP_DIGEST_SIZE SHA256_DIGEST_SIZE #define OCSP_DIGEST_SIZE SHA256_DIGEST_SIZE
@@ -1268,8 +1268,8 @@ typedef struct OCSP_Entry OCSP_Entry;
typedef struct CertStatus CertStatus; typedef struct CertStatus CertStatus;
#endif #endif
struct OCSP_Entry { struct OcspEntry {
OCSP_Entry* next; /* next entry */ OcspEntry* next; /* next entry */
byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */
byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */
CertStatus* status; /* OCSP response list */ CertStatus* status; /* OCSP response list */
@@ -1284,7 +1284,7 @@ struct OCSP_Entry {
/* wolfSSL OCSP controller */ /* wolfSSL OCSP controller */
struct WOLFSSL_OCSP { struct WOLFSSL_OCSP {
WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ 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 */ wolfSSL_Mutex ocspLock; /* OCSP list lock */
}; };
@@ -1577,14 +1577,15 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions);
typedef struct { typedef struct {
byte status_type; byte status_type;
union { union {
OcspRequest ocspRequest; OcspRequest ocsp;
} data; } request;
} CertificateStatusRequest; } CertificateStatusRequest;
WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions,
byte status_type); byte status_type);
WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert);
WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl);
#endif #endif

View File

@@ -40,6 +40,8 @@ WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*);
WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic); WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic);
WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*); WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*);
WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp,
OcspRequest* ocspRequest);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -1419,6 +1419,9 @@ enum {
WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl,
unsigned char status_type); unsigned char status_type);
WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx,
unsigned char status_type);
#endif #endif
#endif #endif

View File

@@ -709,25 +709,22 @@ struct OcspResponse {
struct OcspRequest { struct OcspRequest {
byte issuerHash[KEYID_SIZE]; byte issuerHash[KEYID_SIZE];
byte issuerKeyHash[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; int serialSz;
byte* url; /* copy of the extAuthInfo in source cert */
int urlSz;
byte nonce[MAX_OCSP_NONCE_SZ]; byte nonce[MAX_OCSP_NONCE_SZ];
int nonceSz; int nonceSz;
byte useNonce;
byte* request; /* pointer to the destination ASN.1 buffer; NOT OWNED */
word32 requestSz; /* length of the destination buffer */
}; };
WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32);
WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*); WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*);
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte);
byte, byte*, word32);
WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*);
WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*); WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32);
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*); WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*);

View File

@@ -286,7 +286,8 @@
DYNAMIC_TYPE_SIGNATURE = 45, DYNAMIC_TYPE_SIGNATURE = 45,
DYNAMIC_TYPE_HASHES = 46, DYNAMIC_TYPE_HASHES = 46,
DYNAMIC_TYPE_SRP = 47, DYNAMIC_TYPE_SRP = 47,
DYNAMIC_TYPE_COOKIE_PWD = 48 DYNAMIC_TYPE_COOKIE_PWD = 48,
DYNAMIC_TYPE_OCSP_REQUEST = 49,
}; };
/* max error buffer string size */ /* max error buffer string size */