From 14fa980dad2543d772ecc3946ca3629f46d3173b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sun, 25 Oct 2015 21:21:41 -0300 Subject: [PATCH] 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; --- examples/client/client.c | 5 +- src/internal.c | 24 +-- src/ocsp.c | 301 ++++++++++++++++++++++---------------- src/ssl.c | 9 ++ src/tls.c | 77 +++++++--- wolfcrypt/src/asn.c | 69 +++++---- wolfssl/error-ssl.h | 1 + wolfssl/internal.h | 27 ++-- wolfssl/ocsp.h | 2 + wolfssl/ssl.h | 3 + wolfssl/wolfcrypt/asn.h | 17 +-- wolfssl/wolfcrypt/types.h | 3 +- 12 files changed, 332 insertions(+), 206 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 1821a0894..651bf0819 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -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); diff --git a/src/internal.c b/src/internal.c index b22fef72a..ce5f1326d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -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"; diff --git a/src/ocsp.c b/src/ocsp.c index ae8cb8978..aa1a97252 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -34,59 +34,68 @@ #include #include +#ifdef NO_INLINE + #include +#else + #include +#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; } diff --git a/src/ssl.c b/src/ssl.c index fedee84f3..8b5a2efb8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -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 */ diff --git a/src/tls.c b/src/tls.c index 1b20f96e9..03fe2f409 100644 --- a/src/tls.c +++ b/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; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 7a981d8f2..1b8ba6504 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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) { diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 37952a318..bfccee9cd 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -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 !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index dce8acbbd..ee961573e 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -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 diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 77a4157ee..dc76ca16e 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -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" */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 24bbfb0f3..b507df897 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -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 diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 290d312f3..f18402e35 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -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*); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index d97636e0a..9532c26d9 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -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 */