diff --git a/configure.ac b/configure.ac index 11c5bd149..e7bd09bad 100644 --- a/configure.ac +++ b/configure.ac @@ -1676,6 +1676,26 @@ then fi fi +# Certificate Status Request v2 : a.k.a. OCSP stapling v2 +AC_ARG_ENABLE([ocspstapling2], + [AS_HELP_STRING([--enable-ocspstapling2],[Enable Certificate Status Request v2 - a.k.a. OCSP Stapling v2 (default: disabled)])], + [ ENABLED_CERTIFICATE_STATUS_REQUEST_V2=$enableval ], + [ ENABLED_CERTIFICATE_STATUS_REQUEST_V2=no ] + ) + +if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST_V2" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_CERTIFICATE_STATUS_REQUEST_V2" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + AM_CONDITIONAL([BUILD_OCSP], [test "x$ENABLED_OCSP" = "xyes"]) + fi +fi + # Renegotiation Indication - (FAKE Secure Renegotiation) AC_ARG_ENABLE([renegotiation-indication], [AS_HELP_STRING([--enable-renegotiation-indication],[Enable Renegotiation Indication (default: disabled)])], @@ -2720,6 +2740,7 @@ echo " * ALPN: $ENABLED_ALPN" echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" echo " * Certificate Status Request: $ENABLED_CERTIFICATE_STATUS_REQUEST" +echo " * Certificate Status Request v2: $ENABLED_CERTIFICATE_STATUS_REQUEST_V2" echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" echo " * Session Ticket: $ENABLED_SESSION_TICKET" echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" diff --git a/examples/client/client.c b/examples/client/client.c index f5d005acd..79d735b44 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -358,7 +358,8 @@ static void Usage(void) printf("-o Perform OCSP lookup on peer certificate\n"); printf("-O Perform OCSP lookup using as responder\n"); #endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) printf("-W Use OCSP Stapling\n"); #endif #ifdef ATOMIC_USER @@ -440,7 +441,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_TRUNCATED_HMAC byte truncatedHMAC = 0; #endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) byte statusRequest = 0; #endif @@ -674,7 +676,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; case 'W' : - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) statusRequest = 1; #endif break; @@ -1010,6 +1013,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_EnableOCSP(ctx, 0); } #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (statusRequest) { + if (wolfSSL_UseCertificateStatusRequestV2(ssl, WOLFSSL_CSR2_OCSP, + WOLFSSL_CSR2_OCSP_USE_NONCE) != SSL_SUCCESS) + err_sys("UseCertificateStatusRequest failed"); + + wolfSSL_CTX_EnableOCSP(ctx, 0); + } +#endif tcp_connect(&sockfd, host, port, doDTLS, ssl); diff --git a/examples/server/server.c b/examples/server/server.c index 56a0c680d..000d35a1c 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -725,7 +725,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE); } #endif -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) if (wolfSSL_CTX_EnableOCSPStapling(ctx) != SSL_SUCCESS) err_sys("can't enable OCSP Stapling Certificate Manager"); if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) diff --git a/src/internal.c b/src/internal.c index 905e88a95..163c34d5e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4822,9 +4822,11 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, return BUFFER_ERROR; switch (status_type) { - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - case WOLFSSL_CSR_OCSP: { + /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */ + case WOLFSSL_CSR2_OCSP: { OcspRequest* request = TLSX_CSR_GetRequest(ssl->extensions); #ifdef WOLFSSL_SMALL_STACK @@ -4842,6 +4844,12 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + ssl->status_request_v2 = 0; + break; + } + #endif return BUFFER_ERROR; } while(0); @@ -8147,7 +8155,8 @@ int SendCertificateRequest(WOLFSSL* ssl) } -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer status) { byte* output = NULL; @@ -8232,9 +8241,15 @@ int SendCertificateStatus(WOLFSSL* ssl) status_type = ssl->status_request; #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + status_type = status_type ? status_type : ssl->status_request_v2; +#endif + switch (status_type) { -#if defined HAVE_CERTIFICATE_STATUS_REQUEST - case WOLFSSL_CSR_OCSP: { +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + /* case WOLFSSL_CSR_OCSP: */ + case WOLFSSL_CSR2_OCSP: { OcspRequest* request = ssl->ctx->certOcspRequest; buffer response = {NULL, 0}; @@ -8321,6 +8336,11 @@ int SendCertificateStatus(WOLFSSL* ssl) break; #endif +#if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2 + case WOLFSSL_CSR2_OCSP_MULTI: + break; +#endif + default: break; } diff --git a/src/ssl.c b/src/ssl.c index 38c7d7ea7..e7cecf9f3 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -826,6 +826,31 @@ int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type, #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +int wolfSSL_UseCertificateStatusRequestV2(WOLFSSL* ssl, byte status_type, + byte options) +{ + if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type, + options); +} + + +int wolfSSL_CTX_UseCertificateStatusRequestV2(WOLFSSL_CTX* ctx, + byte status_type, byte options) +{ + if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type, + options); +} + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + /* Elliptic Curves */ #ifdef HAVE_SUPPORTED_CURVES #ifndef NO_WOLFSSL_CLIENT @@ -1643,7 +1668,8 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) #ifdef HAVE_OCSP if (cm->ocsp) FreeOCSP(cm->ocsp, 1); - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) if (cm->ocsp_stapling) FreeOCSP(cm->ocsp_stapling, 1); #endif @@ -3473,7 +3499,8 @@ int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm) if (cm == NULL) return BAD_FUNC_ARG; - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) if (cm->ocsp_stapling == NULL) { cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap, DYNAMIC_TYPE_OCSP); @@ -3669,7 +3696,8 @@ int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb, return BAD_FUNC_ARG; } -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling"); diff --git a/src/tls.c b/src/tls.c index 652c6dabf..ba8bd1a7d 100644 --- a/src/tls.c +++ b/src/tls.c @@ -919,7 +919,7 @@ static word16 TLSX_ALPN_GetSize(ALPN *list) length++; /* protocol name length is on one byte */ length += (word16)XSTRLEN(alpn->protocol_name); } - + return length; } @@ -946,7 +946,7 @@ static word16 TLSX_ALPN_Write(ALPN *list, byte *output) /* writing list length */ c16toa(offset - OPAQUE16_LEN, output); - + return offset; } @@ -1917,6 +1917,7 @@ static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) if (csr->request.ocsp.nonceSz) size += OCSP_NONCE_EXT_SZ; + break; } } #endif @@ -1949,7 +1950,7 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, length = EncodeOcspRequestExtensions( &csr->request.ocsp, output + offset + OPAQUE16_LEN, - MAX_OCSP_EXT_SZ); + OCSP_NONCE_EXT_SZ); c16toa(length, output + offset); offset += OPAQUE16_LEN + length; @@ -2052,6 +2053,13 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, break; } + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) + return 0; + #endif + + /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, 0); if (ret != SSL_SUCCESS) @@ -2187,6 +2195,301 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ +/******************************************************************************/ +/* Certificate Status Request v2 */ +/******************************************************************************/ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2) +{ + CertificateStatusRequestItemV2* next; + + for (; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + FreeOcspRequest(&csr2->request.ocsp); + break; + } + + XFREE(csr2, NULL, DYNAMIC_TYPE_TLSX); + } +} + +static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2, + byte isRequest) +{ + word16 size = 0; + + /* shut up compiler warnings */ + (void) csr2; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + CertificateStatusRequestItemV2* next; + + for (size = OPAQUE16_LEN; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + size += ENUM_LEN + 3 * OPAQUE16_LEN; + + if (csr2->request.ocsp.nonceSz) + size += OCSP_NONCE_EXT_SZ; + break; + } + } + } +#endif + + return size; +} + +static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, + byte* output, byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr2; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset; + word16 length; + + for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) { + /* status_type */ + output[offset++] = csr2->status_type; + + /* request */ + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* request_length */ + length = 2 * OPAQUE16_LEN; + + if (csr2->request.ocsp.nonceSz) + length += OCSP_NONCE_EXT_SZ; + + c16toa(length, output + offset); + offset += OPAQUE16_LEN; + + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + length = 0; + + if (csr2->request.ocsp.nonceSz) + length = EncodeOcspRequestExtensions( + &csr2->request.ocsp, + output + offset + OPAQUE16_LEN, + OCSP_NONCE_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + break; + } + } + + /* list size */ + c16toa(offset - OPAQUE16_LEN, output); + + return offset; + } +#endif + + return 0; +} + +static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* shut up compiler warnings */ + (void) ssl; (void) input; + + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data + : NULL; + + if (!csr2) { + /* look at context level */ + + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2); + csr2 = extension ? extension->data : NULL; + + if (!csr2) + return BUFFER_ERROR; /* unexpected extension */ + } + + ssl->status_request_v2 = 1; + + return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ +#endif + } + else { +#ifndef NO_WOLFSSL_SERVER + byte status_type; + word16 request_length; + word16 offset = 0; + word16 size = 0; + + /* list size */ + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - OPAQUE16_LEN != request_length) + return BUFFER_ERROR; + + while (length > offset) { + if (length - offset < ENUM_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + status_type = input[offset++]; + + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - offset < request_length) + return BUFFER_ERROR; + + switch (status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* skip responder_id_list */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + /* skip request_extensions */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + if (offset > length) + return BUFFER_ERROR; + + /* is able to send OCSP response? */ + if (ssl->ctx->cm == NULL + || !ssl->ctx->cm->ocspStaplingEnabled) + continue; + break; + + default: + /* unkown status type, skipping! */ + offset += request_length; + continue; + } + + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) + return 0; + #endif + + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + status_type, 0); + if (ret != SSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2); + ssl->status_request_v2 = status_type; + + return 0; + } +#endif + } + + return 0; +} + +int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, + byte options) +{ + TLSX* extension = NULL; + CertificateStatusRequestItemV2* csr2 = NULL; + int ret = 0; + + if (!extensions) + return BAD_FUNC_ARG; + + if (status_type != WOLFSSL_CSR2_OCSP + && status_type != WOLFSSL_CSR2_OCSP_MULTI) + return BAD_FUNC_ARG; + + csr2 = (CertificateStatusRequestItemV2*) + XMALLOC(sizeof(CertificateStatusRequestItemV2), NULL, DYNAMIC_TYPE_TLSX); + if (!csr2) + return MEMORY_E; + + ForceZero(csr2, sizeof(CertificateStatusRequestItemV2)); + + csr2->status_type = status_type; + csr2->options = options; + csr2->next = NULL; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) { + WC_RNG rng; + + if (wc_InitRng(&rng) == 0) { + if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp.nonce, + MAX_OCSP_NONCE_SZ) == 0) + csr2->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + break; + } + + /* append new item */ + if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) { + CertificateStatusRequestItemV2* last = + (CertificateStatusRequestItemV2*)extension->data; + + for (; last->next; last = last->next); + + last->next = csr2; + } + else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2))) { + XFREE(csr2, NULL, DYNAMIC_TYPE_TLSX); + return ret; + } + + return SSL_SUCCESS; +} + +#define CSR2_FREE_ALL TLSX_CSR2_FreeAll +#define CSR2_GET_SIZE TLSX_CSR2_GetSize +#define CSR2_WRITE TLSX_CSR2_Write +#define CSR2_PARSE TLSX_CSR2_Parse + +#else + +#define CSR2_FREE_ALL(data) +#define CSR2_GET_SIZE(a, b) 0 +#define CSR2_WRITE(a, b, c) 0 +#define CSR2_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + /******************************************************************************/ /* Supported Elliptic Curves */ /******************************************************************************/ @@ -3400,6 +3703,10 @@ void TLSX_FreeAll(TLSX* list) CSR_FREE_ALL(extension->data); break; + case TLSX_STATUS_REQUEST_V2: + CSR2_FREE_ALL(extension->data); + break; + case TLSX_RENEGOTIATION_INFO: SCR_FREE_ALL(extension->data); break; @@ -3471,6 +3778,10 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) length += CSR_GET_SIZE(extension->data, isRequest); break; + case TLSX_STATUS_REQUEST_V2: + length += CSR2_GET_SIZE(extension->data, isRequest); + break; + case TLSX_RENEGOTIATION_INFO: length += SCR_GET_SIZE(extension->data, isRequest); break; @@ -3545,6 +3856,11 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, isRequest); break; + case TLSX_STATUS_REQUEST_V2: + offset += CSR2_WRITE(extension->data, output + offset, + isRequest); + break; + case TLSX_RENEGOTIATION_INFO: offset += SCR_WRITE(extension->data, output + offset, isRequest); @@ -4044,6 +4360,12 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, ret = CSR_PARSE(ssl, input + offset, size, isRequest); break; + case TLSX_STATUS_REQUEST_V2: + WOLFSSL_MSG("Certificate Status Request v2 extension received"); + + ret = CSR2_PARSE(ssl, input + offset, size, isRequest); + break; + case TLSX_RENEGOTIATION_INFO: WOLFSSL_MSG("Secure Renegotiation extension received"); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 728a8f737..a633dfe50 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8860,34 +8860,34 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]); totalSz += seqSz[5] = SetExplicit(2, totalSz, seqArray[5]); - if (totalSz < size) - { - totalSz = 0; + if (totalSz > size) + return 0; - XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); - totalSz += seqSz[5]; + totalSz = 0; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); - totalSz += seqSz[4]; + XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); + totalSz += seqSz[5]; - XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); - totalSz += seqSz[3]; + XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); + totalSz += seqSz[4]; - XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); - totalSz += seqSz[2]; + XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); + totalSz += seqSz[3]; - XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId)); - totalSz += (word32)sizeof(NonceObjId); + XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); + totalSz += seqSz[2]; - XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); - totalSz += seqSz[1]; + XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId)); + totalSz += (word32)sizeof(NonceObjId); - XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); - totalSz += seqSz[0]; + XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); + totalSz += seqSz[1]; - XMEMCPY(output + totalSz, req->nonce, req->nonceSz); - totalSz += req->nonceSz; - } + XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); + totalSz += seqSz[0]; + + XMEMCPY(output + totalSz, req->nonce, req->nonceSz); + totalSz += req->nonceSz; return totalSz; } @@ -8919,7 +8919,7 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) extSz = 0; if (req->nonceSz) - extSz = EncodeOcspRequestExtensions(req, extArray, MAX_OCSP_EXT_SZ); + extSz = EncodeOcspRequestExtensions(req, extArray, OCSP_NONCE_EXT_SZ); totalSz = algoSz + issuerSz + issuerKeySz + snSz; for (i = 4; i >= 0; i--) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index a553bddba..67a535060 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1364,7 +1364,8 @@ struct WOLFSSL_CERT_MANAGER { void* heap; /* heap helper */ WOLFSSL_CRL* crl; /* CRL checker */ WOLFSSL_OCSP* ocsp; /* OCSP checker */ -#if !defined(NO_WOLFSSL_SEVER) && defined(HAVE_CERTIFICATE_STATUS_REQUEST) +#if !defined(NO_WOLFSSL_SEVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) WOLFSSL_OCSP* ocsp_stapling; /* OCSP checker for OCSP stapling */ #endif char* ocspOverrideURL; /* use this responder */ @@ -1470,6 +1471,7 @@ typedef enum { TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stappling */ TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ + TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stappling v2 */ TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ TLSX_SESSION_TICKET = 0x0023, TLSX_RENEGOTIATION_INFO = 0xff01 @@ -1504,6 +1506,7 @@ WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, || defined(HAVE_MAX_FRAGMENT) \ || defined(HAVE_TRUNCATED_HMAC) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ || defined(HAVE_SUPPORTED_CURVES) \ || defined(HAVE_ALPN) \ || defined(HAVE_QSH) \ @@ -1594,6 +1597,24 @@ WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); #endif +/** Certificate Status Request v2 - RFC 6961 */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +typedef struct CSRIv2 { + byte status_type; + byte options; + word16 request_length; + union { + OcspRequest ocsp; + } request; + struct CSRIv2* next; +} CertificateStatusRequestItemV2; + +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, + byte status_type, byte options); + +#endif + /** Supported Elliptic Curves - RFC 4492 (session 4) */ #ifdef HAVE_SUPPORTED_CURVES @@ -2485,6 +2506,9 @@ struct WOLFSSL { #ifdef HAVE_CERTIFICATE_STATUS_REQUEST byte status_request; #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + byte status_request_v2; + #endif #ifdef HAVE_SECURE_RENEGOTIATION SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */ #endif /* user turned on */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 415b4bd60..9da9c4360 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1439,6 +1439,30 @@ WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, #endif #endif +/* Certificate Status Request v2 */ +/* Certificate Status Type */ +enum { + WOLFSSL_CSR2_OCSP = 1, + WOLFSSL_CSR2_OCSP_MULTI = 2 +}; + +/* Certificate Status v2 Options (flags) */ +enum { + WOLFSSL_CSR2_OCSP_USE_NONCE = 0x01 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseCertificateStatusRequestV2(WOLFSSL* ssl, + unsigned char status_type, unsigned char options); + +WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequestV2(WOLFSSL_CTX* ctx, + unsigned char status_type, unsigned char options); + +#endif +#endif + /* Elliptic Curves */ enum { WOLFSSL_ECC_SECP160R1 = 0x10,