Merge pull request #10922 from aidangarske/fenrir-asn-strict

Enforce RFC 5280 extension MUSTs under WOLFSSL_NO_ASN_STRICT and validate DTLS 1.3 legacy_session_id echo
This commit is contained in:
David Garske
2026-07-22 14:12:33 -07:00
committed by GitHub
93 changed files with 748 additions and 123 deletions
+3
View File
@@ -7,6 +7,9 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
permissions:
contents: read
jobs:
build:
+3
View File
@@ -15,6 +15,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3 -1
View File
@@ -71,10 +71,12 @@ on:
concurrency:
# Same branch push cancels other jobs. Other PR branches untouched
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
async_examples:
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -7,6 +7,9 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
permissions:
contents: read
jobs:
build:
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
+3
View File
@@ -7,6 +7,9 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
permissions:
contents: read
jobs:
build:
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
+3
View File
@@ -10,6 +10,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -10,6 +10,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
# Build wolfSSL with -DWOLFSSL_EMNET using the clean-room shim in
+3
View File
@@ -14,6 +14,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
# Regression test for the memLock / pthread.h guard misalignment in
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -14,6 +14,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -14,6 +14,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
env:
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -14,6 +14,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
env:
+3
View File
@@ -11,6 +11,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
load-targets:
# Only run from the wolfssl org to avoid burning forks' CI minutes
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
# clang has better sanitizer support
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
env:
+3
View File
@@ -14,6 +14,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+13 -1
View File
@@ -27,6 +27,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
@@ -436,7 +439,16 @@ jobs:
{"name": "opensslextra-no-filesystem-no-bio", "minutes": 0.9,
"configure": ["--enable-opensslextra", "--disable-filesystem", "CPPFLAGS=-DNO_BIO"]},
{"name": "no-examples-no-malloc", "minutes": 0.8,
"configure": ["--disable-examples", "CPPFLAGS=-DWOLFSSL_NO_MALLOC"]}
"configure": ["--disable-examples", "CPPFLAGS=-DWOLFSSL_NO_MALLOC"]},
{"comment": "WOLFSSL_NO_ASN_STRICT still enforces the RFC 5280 4.2 and 4.2.1.10 MUSTs",
"name": "no-asn-strict-certs",
"configure": ["--enable-testcert", "--enable-opensslextra", "--enable-certgen",
"--enable-certreq", "--enable-certext", "--enable-ecc",
"CPPFLAGS=-DWOLFSSL_NO_ASN_STRICT -DWOLFSSL_CUSTOM_OID -DHAVE_OID_ENCODING -DWOLFSSL_ALT_NAMES"]},
{"comment": "wolfSSL <= 5.9.0 DTLS 1.3 legacy_session_id echo compatibility shim",
"name": "dtls13-echo-legacy-session-id",
"configure": ["--enable-dtls", "--enable-dtls13", "--enable-session-ticket",
"--enable-ecc", "CPPFLAGS=-DWOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID"]}
]
EOF
.github/scripts/parallel-make-check.py \
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -8,6 +8,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -15,6 +15,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -13,6 +13,9 @@ on:
env:
NETXDUO_REF: v6.4.3_rel
permissions:
contents: read
jobs:
build:
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.draft == false }}
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -7,6 +7,9 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
permissions:
contents: read
jobs:
build:
+3
View File
@@ -23,6 +23,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
windows_arm64_build:
name: Windows ARM64 Build Test
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
@@ -12,6 +12,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
WOLFBOOT_REPO: https://github.com/wolfSSL/wolfBoot.git
WOLFBOOT_BRANCH: master
+3
View File
@@ -16,6 +16,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+3
View File
@@ -11,6 +11,9 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
+2 -2
View File
@@ -866,8 +866,8 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements,
ch->sessionId.size);
#else
/* RFC 9147 Section 5.3: DTLS 1.3 ServerHello must have empty
* legacy_session_id_echo. Don't copy the client's session ID. */
/* RFC 9147 Section 5: "DTLS servers MUST NOT echo the
* legacy_session_id value from the client." */
nonConstSSL->session->sessionIDSz = 0;
#endif
nonConstSSL->options.cipherSuite0 = cs.cipherSuite0;
+32 -9
View File
@@ -41,7 +41,16 @@
* WOLFSSL_EARLY_DATA_GROUP: Group early data with ClientHello default: off
* WOLFSSL_POST_HANDSHAKE_AUTH: Post-handshake client auth default: off
* WOLFSSL_TLS13_TICKET_BEFORE_FINISHED: Send NewSessionTicket default: off
* before client Finished message
* before client Finished message. Violates the
* RFC 8446 Section 4.6.1 ordering requirement; for
* interop with peers that expect the early ticket.
* WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID: Echo legacy_session_id default: off
* in DTLS 1.3. Violates RFC 9147 Section 5 ("DTLS
* servers MUST NOT echo the legacy_session_id
* value from the client"). A server built with this
* option echoes the session ID, which a compliant
* client rejects, so enable it only where the peer
* is wolfSSL <= 5.9.0 or shares this option.
* WOLFSSL_NO_CLIENT_AUTH: Disable TLS 1.3 client authentication default: off
* WOLFSSL_NO_CLIENT_CERT_ERROR: Require client certificate default: off
* WOLFSSL_CERT_SETUP_CB: Certificate setup callback default: off
@@ -5855,12 +5864,12 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|| ssl->options.dtls
#endif
) {
/* RFC 9147 Section 5.3 / RFC 9001 Section 8.4: DTLS 1.3 and QUIC
/* RFC 9147 Section 5 / RFC 9001 Section 8.4: DTLS 1.3 and QUIC
* ServerHello must have empty legacy_session_id_echo. */
int requireEmptyEcho = 1;
#ifdef WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID
/* Compat: a wolfSSL <= 5.9.0 DTLS 1.3 server echoes the client's
* legacy_session_id; accept any echo. */
* legacy_session_id back instead of omitting it. */
if (ssl->options.dtls)
requireEmptyEcho = 0;
#endif
@@ -5869,6 +5878,19 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER);
return INVALID_PARAMETER;
}
#ifdef WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID
/* An echoing wolfSSL <= 5.9.0 server must still send back what was
* sent (RFC 8446 Section 4.1.3), so don't accept an arbitrary value.
* An empty echo is the compliant server case and stays acceptable. */
if (!requireEmptyEcho && args->sessIdSz != 0 &&
(args->sessIdSz != ssl->session->sessionIDSz ||
XMEMCMP(ssl->session->sessionID, args->sessId,
args->sessIdSz) != 0)) {
WOLFSSL_MSG("Server sent different session id");
WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER);
return INVALID_PARAMETER;
}
#endif
}
else
#endif /* WOLFSSL_QUIC || WOLFSSL_DTLS13 */
@@ -7184,7 +7206,8 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie)
/* Reconstruct the HelloRetryMessage for handshake hash. */
sessIdSz = ssl->session->sessionIDSz;
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID)
/* RFC 9147 Section 5.3: DTLS 1.3 must use empty legacy_session_id. */
/* RFC 9147 Section 5: a DTLS 1.3 server does not echo the session ID, so
* the reconstructed transcript must not carry one either. */
if (ssl->options.dtls)
sessIdSz = 0;
#endif
@@ -7665,9 +7688,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ERROR_OUT(BUFFER_ERROR, exit_dch);
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID)
/* RFC 9147 Section 5.3: DTLS 1.3 ServerHello must have empty
* legacy_session_id_echo. Don't store the client's value so it
* won't be echoed in SendTls13ServerHello. */
/* RFC 9147 Section 5: "DTLS servers MUST NOT echo the legacy_session_id
* value from the client." Don't store it so SendTls13ServerHello can't
* echo it. */
if (ssl->options.dtls) {
ssl->session->sessionIDSz = 0;
}
@@ -8274,8 +8297,8 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID)
if (ssl->options.dtls) {
/* RFC 9147 Section 5.3: DTLS 1.3 ServerHello must have empty
* legacy_session_id_echo. */
/* RFC 9147 Section 5: "DTLS servers MUST NOT echo the
* legacy_session_id value from the client." */
output[idx++] = 0;
}
else
+111
View File
@@ -24433,6 +24433,51 @@ static word32 build_registeredID_san(byte* out, word32 outSz)
return (word32)sizeof(ridSan);
}
/* Build a SubjectAltName extension value (a SEQUENCE wrapping a single
* directoryName GeneralName) holding the Name "CN=<val7>". */
static word32 build_dirName_san(byte* out, word32 outSz, const char* val7)
{
static const byte prefix[] = {
0x30, 0x16, /* SEQUENCE, 22 */
0xA4, 0x14, /* [4] dirName, 20 */
0x30, 0x12, /* Name SEQUENCE, 18 */
0x31, 0x10, /* RDN SET, 16 */
0x30, 0x0E, /* ATV SEQUENCE, 14 */
0x06, 0x03, 0x55, 0x04, 0x03, /* OID 2.5.4.3 (CN) */
0x0C, 0x07 /* UTF8String, 7 */
};
/* The UTF8String length above is baked in, so val7 must be exactly 7. */
if (outSz < sizeof(prefix) + 7 || XSTRLEN(val7) != 7)
return 0;
XMEMCPY(out, prefix, sizeof(prefix));
XMEMCPY(out + sizeof(prefix), val7, 7);
return (word32)(sizeof(prefix) + 7);
}
/* Build a NameConstraints extension value carrying a single excludedSubtree
* ([1]) for the directoryName "CN=<val7>". */
static word32 build_dirName_nameConstraints(byte* out, word32 outSz,
const char* val7)
{
static const byte nc[] = {
0x30, 0x1A, /* SEQUENCE, 26 */
0xA1, 0x18, /* [1] excluded, 24 */
0x30, 0x16, /* GeneralSubtree, 22 */
0xA4, 0x14, /* [4] dirName, 20 */
0x30, 0x12, /* Name SEQUENCE, 18 */
0x31, 0x10, /* RDN SET, 16 */
0x30, 0x0E, /* ATV SEQUENCE, 14 */
0x06, 0x03, 0x55, 0x04, 0x03, /* OID 2.5.4.3 (CN) */
0x0C, 0x07 /* UTF8String, 7 */
};
/* The UTF8String length above is baked in, so val7 must be exactly 7. */
if (outSz < sizeof(nc) + 7 || XSTRLEN(val7) != 7)
return 0;
XMEMCPY(out, nc, sizeof(nc));
XMEMCPY(out + sizeof(nc), val7, 7);
return (word32)(sizeof(nc) + 7);
}
/* Build a NameConstraints extension value with a single excludedSubtree
* carrying a registeredID GeneralName for OID 1.2.3.4. wolfSSL enforces
* registeredID name constraints by byte-comparing OID bodies, so a leaf
@@ -24719,6 +24764,71 @@ static int test_NameConstraints_OtherName(void)
return EXPECT_RESULT();
}
/* Verifies wolfSSL applies an issuing CA's directoryName nameConstraints to a
* leaf's directoryName SAN entries, not just to the subject field (RFC 5280
* 4.2.1.10: "Restrictions of the form directoryName MUST be applied to the
* subject field ... and to any names of type directoryName in the
* subjectAltName extension"). The leaf subject never matches the constraint,
* so only the SAN can trigger it.
*
* Coverage:
* 1. Critical excluded subtree, leaf dirName SAN matches -> reject
* 2. Critical excluded subtree, leaf dirName SAN differs -> accept
* (positive control: pins the rejection to the matching path)
* 3. Non-critical excluded subtree, leaf SAN matches -> reject
* (excluded is enforced regardless of criticality)
*
* A permitted-subtree case is not included: for directoryName the leaf's
* subject field is always checked against the permitted list as well, so the
* generated leaf's subject would drive the result rather than its SAN.
*/
static int test_NameConstraints_DirName(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_ASN_TEMPLATE) && \
defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \
defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \
defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \
defined(WOLFSSL_ALT_NAMES) && defined(WOLFSSL_CUSTOM_OID) && \
defined(HAVE_OID_ENCODING) && !defined(IGNORE_NAME_CONSTRAINTS)
byte sanBlocked[64];
byte sanAllowed[64];
byte ncExcludedBlocked[64];
word32 sanBlockedSz, sanAllowedSz;
word32 ncExcludedBlockedSz;
sanBlockedSz = build_dirName_san(sanBlocked, sizeof(sanBlocked), "blocked");
sanAllowedSz = build_dirName_san(sanAllowed, sizeof(sanAllowed), "allowed");
ncExcludedBlockedSz = build_dirName_nameConstraints(
ncExcludedBlocked, sizeof(ncExcludedBlocked), "blocked");
ExpectIntGT((int)sanBlockedSz, 0);
ExpectIntGT((int)sanAllowedSz, 0);
ExpectIntGT((int)ncExcludedBlockedSz, 0);
/* (1) Critical excluded directoryName matches the leaf's dirName SAN.
* Must be rejected. */
ExpectIntEQ(verify_with_otherName_chain(
ncExcludedBlocked, ncExcludedBlockedSz, 1,
sanBlocked, sanBlockedSz),
WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
/* (2) Positive control: same excluded subtree, leaf carries a DIFFERENT
* dirName SAN, so no match and the chain MUST verify. */
ExpectIntEQ(verify_with_otherName_chain(
ncExcludedBlocked, ncExcludedBlockedSz, 1,
sanAllowed, sanAllowedSz),
0);
/* (3) Non-critical excluded subtree, leaf SAN matches: exclusion is
* enforced regardless of criticality. */
ExpectIntEQ(verify_with_otherName_chain(
ncExcludedBlocked, ncExcludedBlockedSz, 0,
sanBlocked, sanBlockedSz),
WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
#endif
return EXPECT_RESULT();
}
#if defined(WOLFSSL_ASN_TEMPLATE) && \
defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \
defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \
@@ -37591,6 +37701,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_PathLenSelfIssuedAllowed),
TEST_DECL(test_PathLenNoKeyUsage),
TEST_DECL(test_NameConstraints_OtherName),
TEST_DECL(test_NameConstraints_DirName),
TEST_DECL(test_NameConstraints_DnsUriWildcard),
TEST_DECL(test_NameConstraints_SubtreeMinMax),
TEST_DECL(test_ParseSerial0FixtureMatrix),
+5 -6
View File
@@ -1540,16 +1540,15 @@ int test_DecodeAltNames_length_underflow(void)
/* A certificate must not carry two certificatePolicies extensions
* (non-repeatable per RFC 5280 4.2). DecodeCertExtensions calls
* DecodeExtensionType once per extension; with strict ASN.1 (the default) a
* second certificatePolicies extension must be rejected (ASN_OBJECT_ID_E)
* rather than silently overwriting the first - which happened in
* WOLFSSL_CERT_EXT builds without WOLFSSL_SEP before the duplicate guard was
* extended to cover them. */
* DecodeExtensionType once per extension; a second certificatePolicies
* extension must be rejected (ASN_OBJECT_ID_E) rather than silently
* overwriting the first - which happened in WOLFSSL_CERT_EXT builds without
* WOLFSSL_SEP before the duplicate guard was extended to cover them. */
int test_DecodeCertExtensions_dup_certpol(void)
{
EXPECT_DECLS;
#if (defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)) && \
!defined(WOLFSSL_NO_ASN_STRICT) && !defined(NO_CERTS) && !defined(NO_ASN)
!defined(NO_CERTS) && !defined(NO_ASN)
/* Minimal certificatePolicies extnValue: SEQUENCE OF PolicyInformation
* with one policyIdentifier OID 1.2.3.4 (encoded 2A 03 04). */
static const byte policy[] = {
-20
View File
@@ -1024,13 +1024,8 @@ int test_wolfSSL_CertManagerNameConstraint2(void)
wolfSSL_X509_sign(x509, priv, EVP_sha256());
#endif
ExpectNotNull((der = wolfSSL_X509_get_der(x509, &derSz)));
#ifndef WOLFSSL_NO_ASN_STRICT
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
#else
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
#endif
/* check that it still fails if one bad altname and one good altname is in
* the certificate */
@@ -1050,13 +1045,8 @@ int test_wolfSSL_CertManagerNameConstraint2(void)
wolfSSL_X509_sign(x509, priv, EVP_sha256());
#endif
ExpectNotNull((der = wolfSSL_X509_get_der(x509, &derSz)));
#ifndef WOLFSSL_NO_ASN_STRICT
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
#else
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
#endif
/* check it fails with switching position of bad altname */
wolfSSL_X509_free(x509);
@@ -1075,13 +1065,8 @@ int test_wolfSSL_CertManagerNameConstraint2(void)
wolfSSL_X509_sign(x509, priv, EVP_sha256());
#endif
ExpectNotNull((der = wolfSSL_X509_get_der(x509, &derSz)));
#ifndef WOLFSSL_NO_ASN_STRICT
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
#else
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
#endif
wolfSSL_CertManagerFree(cm);
wolfSSL_X509_free(x509);
@@ -1110,13 +1095,8 @@ int test_wolfSSL_CertManagerNameConstraint2(void)
wolfSSL_X509_sign(x509, priv, EVP_sha256());
#endif
ExpectNotNull((der = wolfSSL_X509_get_der(x509, &derSz)));
#ifndef WOLFSSL_NO_ASN_STRICT
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
#else
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
#endif
wolfSSL_CertManagerFree(cm);
wolfSSL_X509_free(x509);
wolfSSL_X509_free(ca);
+172 -8
View File
@@ -1740,6 +1740,19 @@ int test_dtls13_no_session_id_echo(void)
return EXPECT_RESULT();
}
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) && \
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID) && \
defined(HAVE_ECC)
/* RFC 8446 Section 4.1.3: an HRR is a ServerHello carrying this magic random.
* Used to assert a real ServerHello was captured, not an HRR. */
static const byte hrrRandom[RAN_LEN] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
};
#endif
/*-- 5_9_0_compat (test_dtls.c lines 3049,3170) ---*/
int test_dtls13_5_9_0_compat(void)
{
@@ -1754,14 +1767,6 @@ int test_dtls13_5_9_0_compat(void)
char readBuf[1];
/* Pin to SECP256R1 to avoid a PQ-induced key-share HRR */
int groups[] = { WOLFSSL_ECC_SECP256R1 };
/* RFC 8446 Section 4.1.3: an HRR is a ServerHello carrying this magic
* random. Used to assert sub-test 1 is a real ServerHello, not an HRR. */
static const byte hrrRandom[RAN_LEN] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
};
/* --- initial connection: get a real session to carry the session ID --- */
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
@@ -1863,3 +1868,162 @@ int test_dtls13_5_9_0_compat(void)
#endif
return EXPECT_RESULT();
}
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) && \
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID) && \
defined(HAVE_ECC)
/* Drive a compat-build resumption up to the point where the server's
* ServerHello is sitting in the client's inbound buffer, echoing the session
* ID the client sent. Returns 0 on success. */
static int compat_echo_setup(struct test_memio_ctx* test_ctx,
WOLFSSL_CTX** ctx_c, WOLFSSL_CTX** ctx_s, WOLFSSL** ssl_c, WOLFSSL** ssl_s,
WOLFSSL_SESSION** sess)
{
EXPECT_DECLS;
char readBuf[1];
int groups[] = { WOLFSSL_ECC_SECP256R1 };
int echoIdx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ +
OPAQUE16_LEN + RAN_LEN;
XMEMSET(test_ctx, 0, sizeof(*test_ctx));
ExpectIntEQ(test_memio_setup(test_ctx, ctx_c, ctx_s, ssl_c, ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
ExpectIntEQ(wolfSSL_set_groups(*ssl_c, groups, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(test_memio_do_handshake(*ssl_c, *ssl_s, 10, NULL), 0);
ExpectIntEQ(wolfSSL_read(*ssl_c, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(*ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(*sess = wolfSSL_get1_session(*ssl_c));
/* A DTLS 1.3 client carries a ticket-derived session ID (SetTicket), so
* the ClientHello legacy_session_id is non-empty. */
ExpectIntEQ((*sess)->sessionIDSz, ID_LEN);
wolfSSL_free(*ssl_c); *ssl_c = NULL;
wolfSSL_free(*ssl_s); *ssl_s = NULL;
wolfSSL_CTX_free(*ctx_c); *ctx_c = NULL;
wolfSSL_CTX_free(*ctx_s); *ctx_s = NULL;
XMEMSET(test_ctx, 0, sizeof(*test_ctx));
ExpectIntEQ(test_memio_setup(test_ctx, ctx_c, ctx_s, ssl_c, ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
ExpectIntEQ(wolfSSL_set_session(*ssl_c, *sess), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_groups(*ssl_c, groups, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_disable_hrr_cookie(*ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_negotiate(*ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(*ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_negotiate(*ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(*ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* A real ServerHello (not an HRR) echoing the client's session ID. */
ExpectIntGE(test_ctx->c_len, echoIdx + 1 + ID_LEN);
ExpectIntEQ(test_ctx->c_buff[DTLS_RECORD_HEADER_SZ], server_hello);
ExpectIntNE(XMEMCMP(&test_ctx->c_buff[DTLS_RECORD_HEADER_SZ +
DTLS_HANDSHAKE_HEADER_SZ + OPAQUE16_LEN], hrrRandom, RAN_LEN), 0);
ExpectIntEQ(test_ctx->c_buff[echoIdx], ID_LEN);
return EXPECT_RESULT() == TEST_SUCCESS ? 0 : -1;
}
#endif
/* The 5.9.0 compat path accepts an echoed legacy_session_id, but RFC 8446
* Section 4.1.3 still requires the echo to be the value the client sent, so a
* server echoing something else must be rejected. */
int test_dtls13_5_9_0_compat_bad_echo(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) && \
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID) && \
defined(HAVE_ECC)
struct test_memio_ctx test_ctx;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
WOLFSSL_SESSION *sess = NULL;
int echoIdx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ +
OPAQUE16_LEN + RAN_LEN;
ExpectIntEQ(compat_echo_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
&sess), 0);
/* Corrupt the echo so it no longer matches what the client sent. */
if (EXPECT_SUCCESS())
test_ctx.c_buff[echoIdx + 1] ^= 0xFF;
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
WC_NO_ERR_TRACE(INVALID_PARAMETER));
wolfSSL_SESSION_free(sess);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
/* A compat-enabled client must still interoperate with an RFC 9147 compliant
* server, which omits the echo entirely. Rewrite the ServerHello to carry an
* empty legacy_session_id_echo and confirm the client does not reject it. */
int test_dtls13_5_9_0_compat_empty_echo(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) && \
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID) && \
defined(HAVE_ECC)
struct test_memio_ctx test_ctx;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
WOLFSSL_SESSION *sess = NULL;
int echoIdx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ +
OPAQUE16_LEN + RAN_LEN;
/* DTLS record header: ... | length(2) at the end. */
int recLenIdx = DTLS_RECORD_HEADER_SZ - OPAQUE16_LEN;
/* DtlsHandShakeHeader: type(1) | length(3) | seq(2) | fragOff(3) |
* fragLen(3). */
int hsLenIdx = DTLS_RECORD_HEADER_SZ + OPAQUE8_LEN;
int fragLenIdx = hsLenIdx + OPAQUE24_LEN + OPAQUE16_LEN + OPAQUE24_LEN;
word32 hsLen, fragLen;
word16 recLen;
ExpectIntEQ(compat_echo_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
&sess), 0);
if (EXPECT_SUCCESS()) {
byte* b = test_ctx.c_buff;
/* Drop the ID_LEN echo bytes and shrink the three enclosing lengths:
* DTLS record length, handshake length, fragment length. */
XMEMMOVE(&b[echoIdx + 1], &b[echoIdx + 1 + ID_LEN],
(size_t)test_ctx.c_len - (size_t)(echoIdx + 1 + ID_LEN));
b[echoIdx] = 0;
/* c_msg_sizes tracks datagram boundaries separately, and read_cb hands
* out exactly msg_sizes[pos] bytes - keep it in sync with c_len. */
test_ctx.c_len -= ID_LEN;
test_ctx.c_msg_sizes[0] -= ID_LEN;
ato16(&b[recLenIdx], &recLen);
c16toa((word16)(recLen - ID_LEN), &b[recLenIdx]);
ato24(&b[hsLenIdx], &hsLen);
c32to24(hsLen - ID_LEN, &b[hsLenIdx]);
ato24(&b[fragLenIdx], &fragLen);
c32to24(fragLen - ID_LEN, &b[fragLenIdx]);
}
/* The client must accept the empty echo and carry on. The rewrite breaks
* the transcript, so it then waits for a flight that never validates
* rather than rejecting the echo with INVALID_PARAMETER. */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
wolfSSL_SESSION_free(sess);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
+5 -1
View File
@@ -53,6 +53,8 @@ int test_dtls_srtp(void);
int test_dtls13_min_rtx_interval(void);
int test_dtls13_no_session_id_echo(void);
int test_dtls13_5_9_0_compat(void);
int test_dtls13_5_9_0_compat_bad_echo(void);
int test_dtls13_5_9_0_compat_empty_echo(void);
#define TEST_DTLS13_DECLS \
TEST_DECL_GROUP("dtls13", test_dtls13_bad_epoch_ch), \
@@ -76,6 +78,8 @@ int test_dtls13_5_9_0_compat(void);
TEST_DECL_GROUP("dtls13", test_dtls_srtp), \
TEST_DECL_GROUP("dtls13", test_dtls13_min_rtx_interval), \
TEST_DECL_GROUP("dtls13", test_dtls13_no_session_id_echo), \
TEST_DECL_GROUP("dtls13", test_dtls13_5_9_0_compat)
TEST_DECL_GROUP("dtls13", test_dtls13_5_9_0_compat), \
TEST_DECL_GROUP("dtls13", test_dtls13_5_9_0_compat_bad_echo), \
TEST_DECL_GROUP("dtls13", test_dtls13_5_9_0_compat_empty_echo)
#endif /* TESTS_API_DTLS13_H */
+18 -21
View File
@@ -52,7 +52,14 @@ ASN Options:
* RSA_DECODE_EXTRA: Decodes extra information in RSA public key.
* WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName.
* WOLFSSL_NO_ASN_STRICT: Disable strict RFC compliance checks to
restore 3.13.0 behavior.
restore 3.13.0 behavior. It no longer disables these RFC 5280 checks:
duplicate detection on the certificate extensions that use
VERIFY_AND_SET_OID (4.2), rejection of a critical extension whose OID is
unrecognized (4.2, subject to any WC_ASN_UNKNOWN_EXT_CB callback), and
application of directoryName name constraints to subjectAltName entries as
well as the subject (4.2.1.10). It still relaxes the critical check for a
recognized-but-unsupported extension (e.g. certificatePolicies without
WOLFSSL_SEP or WOLFSSL_CERT_EXT) and the CRL duplicate-extension check.
* WOLFSSL_ASN_ALLOW_0_SERIAL: Even if WOLFSSL_NO_ASN_STRICT is not defined,
allow a length=1, but zero value serial number.
* WOLFSSL_NO_OCSP_OPTIONAL_CERTS: Skip optional OCSP certs (responder issuer
@@ -19303,9 +19310,7 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
}
break;
case ASN_DIR_TYPE:
#ifndef WOLFSSL_NO_ASN_STRICT
name = cert->altDirNames;
#endif
/* RFC 5280 section 4.2.1.10
"Restrictions of the form directoryName MUST be
@@ -21720,16 +21725,13 @@ static int DecodeAltSigVal(const byte* input, int sz, DecodedCert* cert)
/* Macro to check if bit is set, if not sets and return success.
Otherwise returns failure */
/* Macro required here because bit-field operation */
#ifndef WOLFSSL_NO_ASN_STRICT
#define VERIFY_AND_SET_OID(bit) \
if ((bit) == 0) \
(bit) = 1; \
else \
return ASN_OBJECT_ID_E;
#else
/* With no strict defined, the verify is skipped */
#define VERIFY_AND_SET_OID(bit) bit = 1;
#endif
/* RFC 5280 4.2 forbids a repeated extension, so a duplicate is rejected even
* under WOLFSSL_NO_ASN_STRICT. */
#define VERIFY_AND_SET_OID(bit) \
if ((bit) == 0) \
(bit) = 1; \
else \
return ASN_OBJECT_ID_E;
/* Parse extension type specific data based on OID sum.
*
@@ -21902,9 +21904,7 @@ WOLFSSL_TEST_VIS int DecodeExtensionType(const byte* input, word32 length,
/* Certificate policies. */
case CERT_POLICY_OID:
#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
/* certificatePolicies is non-repeatable (RFC 5280 4.2). In strict
* mode (the default; VERIFY_AND_SET_OID is a no-op under
* WOLFSSL_NO_ASN_STRICT, like every other extension) reject a
/* certificatePolicies is non-repeatable (RFC 5280 4.2). Reject a
* duplicate regardless of WOLFSSL_SEP - otherwise the second one
* silently overwrites the first (DecodeCertPolicy resets
* extCertPoliciesNb), a policy-authorization confusion. */
@@ -22050,18 +22050,15 @@ WOLFSSL_TEST_VIS int DecodeExtensionType(const byte* input, word32 length,
default:
if (isUnknownExt != NULL)
*isUnknownExt = 1;
/* TINY reaches default: for stripped extensions too, so reject a
* critical one even under NO_ASN_STRICT to stay fail-closed. */
#if !defined(WOLFSSL_NO_ASN_STRICT) || defined(WOLFSSL_X509_TINY)
/* While it is a failure to not support critical extensions,
* still parse the certificate ignoring the unsupported
* extension to allow caller to accept it with the verify
* callback. */
* callback. RFC 5280 4.2 makes this a MUST that
* WOLFSSL_NO_ASN_STRICT does not relax. */
if (critical) {
WOLFSSL_ERROR_VERBOSE(ASN_CRIT_EXT_E);
ret = ASN_CRIT_EXT_E;
}
#endif
break;
}
+141 -54
View File
@@ -1053,6 +1053,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void);
!defined(NO_ECC256) && !defined(NO_ECC_SECP)
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_x509_tiny_test(void);
#endif
#if defined(WOLFSSL_TEST_CERT) && defined(HAVE_ECC) && \
!defined(NO_ECC256) && !defined(NO_ECC_SECP)
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_crit_unknown_ext_test(void);
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_dup_ext_test(void);
#endif
#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) && \
!defined(NO_FILESYSTEM)
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void);
@@ -3145,6 +3150,19 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
TEST_PASS("X509 TINY test passed!\n");
#endif
#if defined(WOLFSSL_TEST_CERT) && defined(HAVE_ECC) && \
!defined(NO_ECC256) && !defined(NO_ECC_SECP)
if ( (ret = cert_crit_unknown_ext_test()) != 0)
TEST_FAIL("CERT CRIT EXT test failed!\n", ret);
else
TEST_PASS("CERT CRIT EXT test passed!\n");
if ( (ret = cert_dup_ext_test()) != 0)
TEST_FAIL("CERT DUP EXT test failed!\n", ret);
else
TEST_PASS("CERT DUP EXT test passed!\n");
#endif
#if defined(WOLFSSL_TEST_CERT) && defined(USE_CERT_BUFFERS_2048) && \
!defined(NO_RSA)
if ( (ret = cert_no_malloc_test()) != 0)
@@ -26906,45 +26924,6 @@ static const byte tinyCert_plain[] = {
0x47, 0xAF, 0x90, 0x70, 0x03, 0x82, 0x8D, 0xCA, 0xEA, 0x38, 0x8F, 0x5E,
0x37, 0xCA,
};
#ifndef WOLFSSL_NO_ASN_STRICT
static const byte tinyCert_critUnknown[] = {
0x30, 0x82, 0x01, 0x9B, 0x30, 0x82, 0x01, 0x40, 0xA0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x14, 0x11, 0xBD, 0xBB, 0x2B, 0x6D, 0x81, 0x95, 0xCF, 0xD1,
0x84, 0x74, 0xE2, 0x45, 0xF1, 0x4B, 0x1B, 0xEA, 0xC2, 0xBC, 0xD6, 0x30,
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30,
0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0C,
0x63, 0x72, 0x69, 0x74, 0x65, 0x78, 0x74, 0x2E, 0x74, 0x65, 0x73, 0x74,
0x30, 0x1E, 0x17, 0x0D, 0x32, 0x36, 0x30, 0x36, 0x33, 0x30, 0x32, 0x30,
0x31, 0x31, 0x32, 0x34, 0x5A, 0x17, 0x0D, 0x33, 0x36, 0x30, 0x36, 0x32,
0x37, 0x32, 0x30, 0x31, 0x31, 0x32, 0x34, 0x5A, 0x30, 0x17, 0x31, 0x15,
0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0C, 0x63, 0x72, 0x69,
0x74, 0x65, 0x78, 0x74, 0x2E, 0x74, 0x65, 0x73, 0x74, 0x30, 0x59, 0x30,
0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08,
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
0x9D, 0xE8, 0xE5, 0xCA, 0x7A, 0x56, 0x38, 0xC6, 0x2F, 0x03, 0xA9, 0x26,
0x6A, 0x4A, 0x39, 0xFC, 0xC4, 0x99, 0xAD, 0xCE, 0x41, 0x17, 0xBE, 0x2C,
0xB9, 0x3E, 0xAB, 0x5F, 0x07, 0x77, 0x93, 0x8C, 0x3F, 0x9C, 0xF2, 0x95,
0x97, 0xE5, 0x01, 0x52, 0x30, 0x08, 0x2A, 0x19, 0x2B, 0x15, 0x68, 0xA3,
0x88, 0x79, 0x9D, 0xA2, 0x87, 0x69, 0x68, 0x85, 0x4F, 0x77, 0x2A, 0x1B,
0x06, 0xF6, 0xAD, 0x6A, 0xA3, 0x6A, 0x30, 0x68, 0x30, 0x1D, 0x06, 0x03,
0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x4B, 0x5C, 0x3E, 0xD2, 0x40,
0x91, 0x80, 0x56, 0xF4, 0xD1, 0xCB, 0x16, 0x56, 0x8B, 0x4F, 0xBC, 0x4F,
0xCA, 0xAD, 0x5C, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
0x30, 0x16, 0x80, 0x14, 0x4B, 0x5C, 0x3E, 0xD2, 0x40, 0x91, 0x80, 0x56,
0xF4, 0xD1, 0xCB, 0x16, 0x56, 0x8B, 0x4F, 0xBC, 0x4F, 0xCA, 0xAD, 0x5C,
0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05,
0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x15, 0x06, 0x09, 0x2B, 0x06, 0x01,
0x04, 0x01, 0x86, 0x8D, 0x1F, 0x01, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x04,
0x03, 0x01, 0x02, 0x03, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00,
0xD8, 0x78, 0x6A, 0x3F, 0xFC, 0x03, 0x1B, 0x7D, 0x8F, 0x8C, 0x2F, 0xC9,
0x80, 0x4B, 0x85, 0x5C, 0x2B, 0xF1, 0x52, 0x82, 0x94, 0x37, 0xE0, 0xA5,
0x49, 0x3F, 0x30, 0xBB, 0xC2, 0xBE, 0xC7, 0xE0, 0x02, 0x21, 0x00, 0xF5,
0xDD, 0x14, 0x04, 0xC8, 0xA2, 0xC0, 0x78, 0x13, 0x43, 0xE8, 0x97, 0xE1,
0xEB, 0xAE, 0x2A, 0x13, 0x3D, 0x46, 0xF3, 0x1D, 0x5D, 0xAA, 0x26, 0x95,
0x18, 0x71, 0x77, 0xF7, 0x46, 0x62, 0xD0,
};
#endif
#ifndef IGNORE_NAME_CONSTRAINTS
static const byte tinyCert_nameConstr[] = {
0x30, 0x82, 0x01, 0xA0, 0x30, 0x82, 0x01, 0x45, 0xA0, 0x03, 0x02, 0x01,
@@ -26985,9 +26964,9 @@ static const byte tinyCert_nameConstr[] = {
};
#endif
/* Exercise the WOLFSSL_X509_TINY profile: a normal cert still parses, a
* critical unknown extension is rejected, and nameConstraints fails closed
* unless the add-back is enabled. Self-signed P-256, parsed with NO_VERIFY. */
/* Exercise the WOLFSSL_X509_TINY profile: a normal cert still parses, and
* nameConstraints fails closed unless the add-back is enabled. Self-signed
* P-256, parsed with NO_VERIFY. */
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_x509_tiny_test(void)
{
wc_test_ret_t ret;
@@ -26999,17 +26978,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_x509_tiny_test(void)
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
#ifndef WOLFSSL_NO_ASN_STRICT
InitDecodedCert(&cert, tinyCert_critUnknown,
(word32)sizeof(tinyCert_critUnknown), NULL);
ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL);
FreeDecodedCert(&cert);
if (ret == 0) /* expected rejection, got accept */
return WC_TEST_RET_ENC_NC;
if (ret != WC_NO_ERR_TRACE(ASN_CRIT_EXT_E))
return WC_TEST_RET_ENC_EC(ret);
#endif
#ifndef IGNORE_NAME_CONSTRAINTS
InitDecodedCert(&cert, tinyCert_nameConstr,
(word32)sizeof(tinyCert_nameConstr), NULL);
@@ -27019,7 +26987,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_x509_tiny_test(void)
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
#else
if (ret == 0) /* expected rejection, got accept */
if (ret == 0) /* expected rejection, got accept */
return WC_TEST_RET_ENC_NC;
if (ret != WC_NO_ERR_TRACE(ASN_NAME_INVALID_E))
return WC_TEST_RET_ENC_EC(ret);
@@ -30941,6 +30909,125 @@ exit_rsa:
#endif /* !NO_RSA */
#if defined(WOLFSSL_TEST_CERT) && defined(HAVE_ECC) && \
!defined(NO_ECC256) && !defined(NO_ECC_SECP)
/* Self-signed P-256 cert with a critical extension of unrecognized OID
* 1.3.6.1.4.1.99999.1. */
static const byte critUnknownExtCert[] = {
0x30, 0x82, 0x01, 0x9B, 0x30, 0x82, 0x01, 0x40, 0xA0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x14, 0x11, 0xBD, 0xBB, 0x2B, 0x6D, 0x81, 0x95, 0xCF, 0xD1,
0x84, 0x74, 0xE2, 0x45, 0xF1, 0x4B, 0x1B, 0xEA, 0xC2, 0xBC, 0xD6, 0x30,
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30,
0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0C,
0x63, 0x72, 0x69, 0x74, 0x65, 0x78, 0x74, 0x2E, 0x74, 0x65, 0x73, 0x74,
0x30, 0x1E, 0x17, 0x0D, 0x32, 0x36, 0x30, 0x36, 0x33, 0x30, 0x32, 0x30,
0x31, 0x31, 0x32, 0x34, 0x5A, 0x17, 0x0D, 0x33, 0x36, 0x30, 0x36, 0x32,
0x37, 0x32, 0x30, 0x31, 0x31, 0x32, 0x34, 0x5A, 0x30, 0x17, 0x31, 0x15,
0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0C, 0x63, 0x72, 0x69,
0x74, 0x65, 0x78, 0x74, 0x2E, 0x74, 0x65, 0x73, 0x74, 0x30, 0x59, 0x30,
0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08,
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
0x9D, 0xE8, 0xE5, 0xCA, 0x7A, 0x56, 0x38, 0xC6, 0x2F, 0x03, 0xA9, 0x26,
0x6A, 0x4A, 0x39, 0xFC, 0xC4, 0x99, 0xAD, 0xCE, 0x41, 0x17, 0xBE, 0x2C,
0xB9, 0x3E, 0xAB, 0x5F, 0x07, 0x77, 0x93, 0x8C, 0x3F, 0x9C, 0xF2, 0x95,
0x97, 0xE5, 0x01, 0x52, 0x30, 0x08, 0x2A, 0x19, 0x2B, 0x15, 0x68, 0xA3,
0x88, 0x79, 0x9D, 0xA2, 0x87, 0x69, 0x68, 0x85, 0x4F, 0x77, 0x2A, 0x1B,
0x06, 0xF6, 0xAD, 0x6A, 0xA3, 0x6A, 0x30, 0x68, 0x30, 0x1D, 0x06, 0x03,
0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x4B, 0x5C, 0x3E, 0xD2, 0x40,
0x91, 0x80, 0x56, 0xF4, 0xD1, 0xCB, 0x16, 0x56, 0x8B, 0x4F, 0xBC, 0x4F,
0xCA, 0xAD, 0x5C, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
0x30, 0x16, 0x80, 0x14, 0x4B, 0x5C, 0x3E, 0xD2, 0x40, 0x91, 0x80, 0x56,
0xF4, 0xD1, 0xCB, 0x16, 0x56, 0x8B, 0x4F, 0xBC, 0x4F, 0xCA, 0xAD, 0x5C,
0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05,
0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x15, 0x06, 0x09, 0x2B, 0x06, 0x01,
0x04, 0x01, 0x86, 0x8D, 0x1F, 0x01, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x04,
0x03, 0x01, 0x02, 0x03, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00,
0xD8, 0x78, 0x6A, 0x3F, 0xFC, 0x03, 0x1B, 0x7D, 0x8F, 0x8C, 0x2F, 0xC9,
0x80, 0x4B, 0x85, 0x5C, 0x2B, 0xF1, 0x52, 0x82, 0x94, 0x37, 0xE0, 0xA5,
0x49, 0x3F, 0x30, 0xBB, 0xC2, 0xBE, 0xC7, 0xE0, 0x02, 0x21, 0x00, 0xF5,
0xDD, 0x14, 0x04, 0xC8, 0xA2, 0xC0, 0x78, 0x13, 0x43, 0xE8, 0x97, 0xE1,
0xEB, 0xAE, 0x2A, 0x13, 0x3D, 0x46, 0xF3, 0x1D, 0x5D, 0xAA, 0x26, 0x95,
0x18, 0x71, 0x77, 0xF7, 0x46, 0x62, 0xD0,
};
/* Self-signed P-256 cert carrying keyUsage twice: digitalSignature first, then
* keyCertSign. A last-wins parse would hand back keyCertSign. */
static const byte dupKeyUsageCert[] = {
0x30, 0x82, 0x01, 0x80, 0x30, 0x82, 0x01, 0x26, 0xA0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x14, 0x4D, 0x16, 0x79, 0x22, 0x7D, 0xA3, 0x8F, 0x66, 0xC2,
0x8B, 0x22, 0x26, 0x3E, 0x8A, 0x17, 0x98, 0x8F, 0xCE, 0xDD, 0x6D, 0x30,
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30,
0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0B,
0x64, 0x75, 0x70, 0x65, 0x78, 0x74, 0x2E, 0x74, 0x65, 0x73, 0x74, 0x30,
0x1E, 0x17, 0x0D, 0x32, 0x36, 0x30, 0x37, 0x31, 0x35, 0x31, 0x37, 0x33,
0x31, 0x32, 0x36, 0x5A, 0x17, 0x0D, 0x33, 0x36, 0x30, 0x37, 0x31, 0x32,
0x31, 0x37, 0x33, 0x31, 0x32, 0x36, 0x5A, 0x30, 0x16, 0x31, 0x14, 0x30,
0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0B, 0x64, 0x75, 0x70, 0x65,
0x78, 0x74, 0x2E, 0x74, 0x65, 0x73, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06,
0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86,
0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xEE, 0x55,
0xE4, 0x63, 0x53, 0x3F, 0x25, 0x93, 0x33, 0xA1, 0xD3, 0xD6, 0x65, 0xD7,
0xE4, 0x39, 0x87, 0x34, 0x3E, 0x72, 0xB5, 0xE7, 0x20, 0xA9, 0xBE, 0x39,
0x23, 0xE0, 0x6B, 0xD5, 0xE2, 0xEB, 0x52, 0x86, 0x2A, 0x1F, 0x54, 0x2A,
0x31, 0x50, 0x1A, 0xE2, 0x4B, 0xC3, 0x3E, 0x09, 0x0A, 0x65, 0x9D, 0x3B,
0xB2, 0xC8, 0x36, 0x56, 0x7C, 0x1A, 0x48, 0x39, 0xD3, 0xAA, 0x74, 0x65,
0x0F, 0xC0, 0xA3, 0x52, 0x30, 0x50, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D,
0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03,
0x02, 0x07, 0x80, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16,
0x04, 0x14, 0x27, 0xE6, 0x35, 0x0E, 0x0F, 0xE5, 0xCA, 0xC3, 0xE8, 0x79,
0x8C, 0x07, 0xB7, 0x2B, 0x61, 0xB4, 0x8F, 0xEC, 0x5A, 0xBB, 0x30, 0x0E,
0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02,
0x02, 0x04, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04,
0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xCC, 0x2F,
0xA2, 0x32, 0x8F, 0x36, 0x54, 0xFB, 0xEC, 0xAF, 0x68, 0x83, 0x29, 0x02,
0x13, 0x87, 0x13, 0x59, 0x38, 0xB0, 0xFB, 0xB4, 0x8F, 0x0F, 0xF7, 0x78,
0xF2, 0xD0, 0x73, 0xA6, 0x33, 0x34, 0x02, 0x20, 0x65, 0x11, 0x64, 0x82,
0x3F, 0x02, 0x06, 0x0B, 0x70, 0xB5, 0x6D, 0x60, 0xA0, 0xF0, 0x84, 0x0E,
0x27, 0x60, 0xF6, 0x88, 0xFD, 0x50, 0xC5, 0xBE, 0x78, 0x6D, 0x90, 0x1A,
0x14, 0x7B, 0x42, 0xE7,
};
/* RFC 5280 4.2 forbids a repeated extension, and WOLFSSL_NO_ASN_STRICT does not
* relax that MUST. */
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_dup_ext_test(void)
{
wc_test_ret_t ret;
DecodedCert cert;
InitDecodedCert(&cert, dupKeyUsageCert, (word32)sizeof(dupKeyUsageCert),
NULL);
ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL);
FreeDecodedCert(&cert);
if (ret == 0) /* expected rejection, got accept */
return WC_TEST_RET_ENC_NC;
if (ret != WC_NO_ERR_TRACE(ASN_OBJECT_ID_E))
return WC_TEST_RET_ENC_EC(ret);
return 0;
}
/* RFC 5280 4.2 makes rejecting an unrecognized critical extension a MUST that
* WOLFSSL_NO_ASN_STRICT does not relax. */
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_crit_unknown_ext_test(void)
{
wc_test_ret_t ret;
DecodedCert cert;
InitDecodedCert(&cert, critUnknownExtCert,
(word32)sizeof(critUnknownExtCert), NULL);
ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL);
FreeDecodedCert(&cert);
if (ret == 0) /* expected rejection, got accept */
return WC_TEST_RET_ENC_NC;
if (ret != WC_NO_ERR_TRACE(ASN_CRIT_EXT_E))
return WC_TEST_RET_ENC_EC(ret);
return 0;
}
#endif
#ifndef NO_DH