From 8e9af5c4b8e83d11904512a070914811f65602e8 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Wed, 15 Jul 2026 14:24:00 -0700 Subject: [PATCH 1/5] 6821 - Reject unknown critical extensions under WOLFSSL_NO_ASN_STRICT --- wolfcrypt/src/asn.c | 7 +-- wolfcrypt/test/test.c | 132 +++++++++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 59 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8b870e3ce0b..81402998e12 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -21795,18 +21795,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; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e4227d9ebbc..c9a386dbd51 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1039,6 +1039,10 @@ 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); +#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); @@ -3114,6 +3118,14 @@ 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"); +#endif + #if defined(WOLFSSL_TEST_CERT) && defined(USE_CERT_BUFFERS_2048) && \ !defined(NO_RSA) if ( (ret = cert_no_malloc_test()) != 0) @@ -26644,45 +26656,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, @@ -26723,9 +26696,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; @@ -26737,17 +26710,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); @@ -26757,7 +26719,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); @@ -30512,6 +30474,68 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) #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, +}; + +/* 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 From 92d5375e77aeac70ca273bad218bc1910b9d4b6d Mon Sep 17 00:00:00 2001 From: aidan garske Date: Wed, 15 Jul 2026 14:26:00 -0700 Subject: [PATCH 2/5] 6822 - Reject duplicate cert extensions under WOLFSSL_NO_ASN_STRICT --- tests/api/test_asn.c | 11 ++++---- wolfcrypt/src/asn.c | 21 ++++++--------- wolfcrypt/test/test.c | 63 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 19 deletions(-) diff --git a/tests/api/test_asn.c b/tests/api/test_asn.c index ab0644f11c5..a91415cecfa 100644 --- a/tests/api/test_asn.c +++ b/tests/api/test_asn.c @@ -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[] = { diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 81402998e12..4006b1eb8fa 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -21465,16 +21465,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. * @@ -21647,9 +21644,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. */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index c9a386dbd51..d9f7e1473ef 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1042,6 +1042,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_x509_tiny_test(void); #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) @@ -3124,6 +3125,11 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ 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) && \ @@ -30516,6 +30522,63 @@ static const byte critUnknownExtCert[] = { 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) From a0cc010217b6517fc3d5f0e449e99f71dd2df996 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Wed, 15 Jul 2026 14:27:26 -0700 Subject: [PATCH 3/5] 6823 - Apply dirName constraints to SANs under WOLFSSL_NO_ASN_STRICT --- .github/workflows/os-check.yml | 7 ++- tests/api.c | 111 +++++++++++++++++++++++++++++++++ tests/api/test_certman.c | 20 ------ wolfcrypt/src/asn.c | 11 +++- 4 files changed, 125 insertions(+), 24 deletions(-) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 25f2b6f8810..bb4c453a47f 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -436,7 +436,12 @@ 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"]} ] EOF .github/scripts/parallel-make-check.py \ diff --git a/tests/api.c b/tests/api.c index 238ea673976..c264f781f55 100644 --- a/tests/api.c +++ b/tests/api.c @@ -24314,6 +24314,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=". */ +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=". */ +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 @@ -24600,6 +24645,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) && \ @@ -37030,6 +37140,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), diff --git a/tests/api/test_certman.c b/tests/api/test_certman.c index 25c203a4b28..973fd494dc7 100644 --- a/tests/api/test_certman.c +++ b/tests/api/test_certman.c @@ -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); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 4006b1eb8fa..cfd7752211c 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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 @@ -19048,9 +19055,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 From 3bab30ff5c8c0409086eb15947d4e31c138a0789 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Wed, 15 Jul 2026 15:27:49 -0700 Subject: [PATCH 4/5] 6824 - Verify echoed legacy_session_id matches the value sent in DTLS 1.3 --- .github/workflows/os-check.yml | 6 +- src/dtls.c | 4 +- src/tls13.c | 41 ++++++-- tests/api/test_dtls13.c | 180 +++++++++++++++++++++++++++++++-- tests/api/test_dtls13.h | 6 +- 5 files changed, 216 insertions(+), 21 deletions(-) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index bb4c453a47f..5efaea93989 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -441,7 +441,11 @@ jobs: "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"]} + "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 \ diff --git a/src/dtls.c b/src/dtls.c index dda4c7bddc6..3c2b4635afc 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -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; diff --git a/src/tls13.c b/src/tls13.c index b8c7dbbc912..a88ccd5df16 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -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 @@ -5854,12 +5863,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 @@ -5868,6 +5877,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 */ @@ -7181,7 +7203,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 @@ -7662,9 +7685,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; } @@ -8271,8 +8294,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 diff --git a/tests/api/test_dtls13.c b/tests/api/test_dtls13.c index 7752fe739c2..25ce580776a 100644 --- a/tests/api/test_dtls13.c +++ b/tests/api/test_dtls13.c @@ -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(); +} diff --git a/tests/api/test_dtls13.h b/tests/api/test_dtls13.h index b175c2418cc..2d2872339fa 100644 --- a/tests/api/test_dtls13.h +++ b/tests/api/test_dtls13.h @@ -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 */ From dd46074153757c7fb816fc5c82e3a525c1b4d0cd Mon Sep 17 00:00:00 2001 From: aidan garske Date: Wed, 15 Jul 2026 16:16:21 -0700 Subject: [PATCH 5/5] 6707 - Add least-privilege permissions block to PR-triggered workflows --- .github/workflows/ada.yml | 3 +++ .github/workflows/aesgcm-siv.yml | 3 +++ .github/workflows/arduino.yml | 4 +++- .github/workflows/async-examples.yml | 3 +++ .github/workflows/async.yml | 3 +++ .github/workflows/bind.yml | 3 +++ .github/workflows/check-cert-chains.yml | 3 +++ .github/workflows/cmake-autoconf.yml | 3 +++ .github/workflows/cmake.yml | 3 +++ .github/workflows/codespell.yml | 3 +++ .github/workflows/cross-wolfclu.yml | 3 +++ .github/workflows/cross-wolfmqtt.yml | 3 +++ .github/workflows/cross-wolfpkcs11.yml | 3 +++ .github/workflows/cross-wolfprovider.yml | 3 +++ .github/workflows/cross-wolfssh.yml | 3 +++ .github/workflows/cross-wolftpm.yml | 3 +++ .github/workflows/cryptocb-only.yml | 3 +++ .github/workflows/curl.yml | 3 +++ .github/workflows/cyrus-sasl.yml | 3 +++ .github/workflows/disable-pk-algs.yml | 3 +++ .github/workflows/docker-Espressif.yml | 3 +++ .github/workflows/emnet-nonblock.yml | 3 +++ .github/workflows/fil-c.yml | 3 +++ .github/workflows/freertos-mem-track.yml | 3 +++ .github/workflows/gencertbuf.yml | 3 +++ .github/workflows/grpc.yml | 3 +++ .github/workflows/haproxy.yml | 3 +++ .github/workflows/hostap-vm.yml | 3 +++ .github/workflows/intelasm-c-fallback.yml | 3 +++ .github/workflows/ipmitool.yml | 3 +++ .github/workflows/jwt-cpp.yml | 3 +++ .github/workflows/krb5.yml | 3 +++ .github/workflows/libspdm.yml | 3 +++ .github/workflows/libssh2.yml | 3 +++ .github/workflows/libvncserver.yml | 3 +++ .github/workflows/linuxkm.yml | 3 +++ .github/workflows/mbedtls.yml | 3 +++ .github/workflows/membrowse-report.yml | 3 +++ .github/workflows/memcached.yml | 3 +++ .github/workflows/mono.yml | 3 +++ .github/workflows/mosquitto.yml | 3 +++ .github/workflows/msmtp.yml | 3 +++ .github/workflows/msys2.yml | 3 +++ .github/workflows/multi-arch.yml | 3 +++ .github/workflows/multi-compiler.yml | 3 +++ .github/workflows/net-snmp.yml | 3 +++ .github/workflows/nginx.yml | 3 +++ .github/workflows/no-malloc.yml | 3 +++ .github/workflows/nss.yml | 3 +++ .github/workflows/ntp.yml | 3 +++ .github/workflows/ocsp.yml | 3 +++ .github/workflows/openldap.yml | 3 +++ .github/workflows/openssh.yml | 3 +++ .github/workflows/openssl-ech.yml | 3 +++ .github/workflows/opensslcoexist.yml | 3 +++ .github/workflows/openvpn.yml | 3 +++ .github/workflows/os-check.yml | 3 +++ .github/workflows/packaging.yml | 3 +++ .github/workflows/pam-ipmi.yml | 3 +++ .github/workflows/pq-all.yml | 3 +++ .github/workflows/pr-commit-check.yml | 3 +++ .github/workflows/psk.yml | 3 +++ .github/workflows/puf.yml | 3 +++ .github/workflows/python.yml | 3 +++ .github/workflows/rng-tools.yml | 3 +++ .github/workflows/rtl8735b.yml | 3 +++ .github/workflows/rust-wrapper.yml | 3 +++ .github/workflows/smallStackSize.yml | 3 +++ .github/workflows/socat.yml | 3 +++ .github/workflows/softhsm.yml | 3 +++ .github/workflows/sssd.yml | 3 +++ .github/workflows/stunnel.yml | 3 +++ .github/workflows/symbol-prefixes.yml | 3 +++ .github/workflows/threadx.yml | 3 +++ .github/workflows/trackmemory.yml | 3 +++ .github/workflows/watcomc.yml | 3 +++ .github/workflows/win-csharp-test.yml | 3 +++ .github/workflows/windows-arm64.yml | 3 +++ .github/workflows/wolfCrypt-Wconversion.yml | 3 +++ .github/workflows/wolfboot-integration.yml | 3 +++ .github/workflows/wolfsm.yml | 3 +++ .github/workflows/xcode.yml | 3 +++ .github/workflows/zephyr-4.x.yml | 3 +++ .github/workflows/zephyr.yml | 3 +++ 84 files changed, 252 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ada.yml b/.github/workflows/ada.yml index 158b3e93976..35bf4672d2b 100644 --- a/.github/workflows/ada.yml +++ b/.github/workflows/ada.yml @@ -7,6 +7,9 @@ on: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] +permissions: + contents: read + jobs: build: diff --git a/.github/workflows/aesgcm-siv.yml b/.github/workflows/aesgcm-siv.yml index f067f747007..b7c250f2e0f 100644 --- a/.github/workflows/aesgcm-siv.yml +++ b/.github/workflows/aesgcm-siv.yml @@ -15,6 +15,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/arduino.yml b/.github/workflows/arduino.yml index 2df14a8edf4..95e27245015 100644 --- a/.github/workflows/arduino.yml +++ b/.github/workflows/arduino.yml @@ -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: diff --git a/.github/workflows/async-examples.yml b/.github/workflows/async-examples.yml index caca4b6c32b..5f55033e328 100644 --- a/.github/workflows/async-examples.yml +++ b/.github/workflows/async-examples.yml @@ -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) }} diff --git a/.github/workflows/async.yml b/.github/workflows/async.yml index b2c2a97e721..0b3f4947a2d 100644 --- a/.github/workflows/async.yml +++ b/.github/workflows/async.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/bind.yml b/.github/workflows/bind.yml index b9cb22772ce..9164461ad4c 100644 --- a/.github/workflows/bind.yml +++ b/.github/workflows/bind.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/check-cert-chains.yml b/.github/workflows/check-cert-chains.yml index 4d4ec11fef9..6c83a49f889 100644 --- a/.github/workflows/check-cert-chains.yml +++ b/.github/workflows/check-cert-chains.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cmake-autoconf.yml b/.github/workflows/cmake-autoconf.yml index 9d4c076e974..9f479872164 100644 --- a/.github/workflows/cmake-autoconf.yml +++ b/.github/workflows/cmake-autoconf.yml @@ -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) }} diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 354f8d9e024..abe2a1ee59a 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -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) }} diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 0bf29f3fbd8..6992ae2be2a 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,6 +10,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cross-wolfclu.yml b/.github/workflows/cross-wolfclu.yml index 39aa09a5f2b..f777283a439 100644 --- a/.github/workflows/cross-wolfclu.yml +++ b/.github/workflows/cross-wolfclu.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cross-wolfmqtt.yml b/.github/workflows/cross-wolfmqtt.yml index fcaf78475e7..fb880d1bda3 100644 --- a/.github/workflows/cross-wolfmqtt.yml +++ b/.github/workflows/cross-wolfmqtt.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cross-wolfpkcs11.yml b/.github/workflows/cross-wolfpkcs11.yml index c321bef90db..bb675e30d6d 100644 --- a/.github/workflows/cross-wolfpkcs11.yml +++ b/.github/workflows/cross-wolfpkcs11.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cross-wolfprovider.yml b/.github/workflows/cross-wolfprovider.yml index ec686c2cbee..ee06be8cf28 100644 --- a/.github/workflows/cross-wolfprovider.yml +++ b/.github/workflows/cross-wolfprovider.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cross-wolfssh.yml b/.github/workflows/cross-wolfssh.yml index b08d42a6c7b..b9cf3946ed4 100644 --- a/.github/workflows/cross-wolfssh.yml +++ b/.github/workflows/cross-wolfssh.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cross-wolftpm.yml b/.github/workflows/cross-wolftpm.yml index ac946369bdd..f490cfcde7d 100644 --- a/.github/workflows/cross-wolftpm.yml +++ b/.github/workflows/cross-wolftpm.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cryptocb-only.yml b/.github/workflows/cryptocb-only.yml index 2d645e93439..537cee3c033 100644 --- a/.github/workflows/cryptocb-only.yml +++ b/.github/workflows/cryptocb-only.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/curl.yml b/.github/workflows/curl.yml index 2bae21ff5be..09739b1f991 100644 --- a/.github/workflows/curl.yml +++ b/.github/workflows/curl.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/cyrus-sasl.yml b/.github/workflows/cyrus-sasl.yml index a05bab33615..5c1ad746e0a 100644 --- a/.github/workflows/cyrus-sasl.yml +++ b/.github/workflows/cyrus-sasl.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/disable-pk-algs.yml b/.github/workflows/disable-pk-algs.yml index 655f48a98f1..880bbb82932 100644 --- a/.github/workflows/disable-pk-algs.yml +++ b/.github/workflows/disable-pk-algs.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/docker-Espressif.yml b/.github/workflows/docker-Espressif.yml index 230ecd9da09..242f0e8d784 100644 --- a/.github/workflows/docker-Espressif.yml +++ b/.github/workflows/docker-Espressif.yml @@ -10,6 +10,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/emnet-nonblock.yml b/.github/workflows/emnet-nonblock.yml index 893379639c6..cc786507a14 100644 --- a/.github/workflows/emnet-nonblock.yml +++ b/.github/workflows/emnet-nonblock.yml @@ -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 diff --git a/.github/workflows/fil-c.yml b/.github/workflows/fil-c.yml index 2a0ff443718..b592870ba6b 100644 --- a/.github/workflows/fil-c.yml +++ b/.github/workflows/fil-c.yml @@ -14,6 +14,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/freertos-mem-track.yml b/.github/workflows/freertos-mem-track.yml index 29ebfaf4a7b..e28aa7f0724 100644 --- a/.github/workflows/freertos-mem-track.yml +++ b/.github/workflows/freertos-mem-track.yml @@ -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 diff --git a/.github/workflows/gencertbuf.yml b/.github/workflows/gencertbuf.yml index aac346ae096..7f5fad9623a 100644 --- a/.github/workflows/gencertbuf.yml +++ b/.github/workflows/gencertbuf.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/grpc.yml b/.github/workflows/grpc.yml index 7095a2970d2..1a443a58bac 100644 --- a/.github/workflows/grpc.yml +++ b/.github/workflows/grpc.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/haproxy.yml b/.github/workflows/haproxy.yml index 10ec6a1aa35..65b7c6a7d5f 100644 --- a/.github/workflows/haproxy.yml +++ b/.github/workflows/haproxy.yml @@ -14,6 +14,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/hostap-vm.yml b/.github/workflows/hostap-vm.yml index d663f5db253..2d66fa60157 100644 --- a/.github/workflows/hostap-vm.yml +++ b/.github/workflows/hostap-vm.yml @@ -14,6 +14,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION env: diff --git a/.github/workflows/intelasm-c-fallback.yml b/.github/workflows/intelasm-c-fallback.yml index 4d3f3ae18e5..127df08a93c 100644 --- a/.github/workflows/intelasm-c-fallback.yml +++ b/.github/workflows/intelasm-c-fallback.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/ipmitool.yml b/.github/workflows/ipmitool.yml index 4f11da7787c..b5df5fbe124 100644 --- a/.github/workflows/ipmitool.yml +++ b/.github/workflows/ipmitool.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION diff --git a/.github/workflows/jwt-cpp.yml b/.github/workflows/jwt-cpp.yml index cd4d6ffa60e..e3263f3f996 100644 --- a/.github/workflows/jwt-cpp.yml +++ b/.github/workflows/jwt-cpp.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/krb5.yml b/.github/workflows/krb5.yml index 55fb7f9e879..80810e9a30b 100644 --- a/.github/workflows/krb5.yml +++ b/.github/workflows/krb5.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/libspdm.yml b/.github/workflows/libspdm.yml index 6294b9a17d1..66318ba68d7 100644 --- a/.github/workflows/libspdm.yml +++ b/.github/workflows/libspdm.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/libssh2.yml b/.github/workflows/libssh2.yml index 2b440e694cc..0a30726d4b5 100644 --- a/.github/workflows/libssh2.yml +++ b/.github/workflows/libssh2.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/libvncserver.yml b/.github/workflows/libvncserver.yml index e73969de0e1..18a0e27ffcf 100644 --- a/.github/workflows/libvncserver.yml +++ b/.github/workflows/libvncserver.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/linuxkm.yml b/.github/workflows/linuxkm.yml index 8922f71bdf0..8c404a4b0c8 100644 --- a/.github/workflows/linuxkm.yml +++ b/.github/workflows/linuxkm.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml index a6fcc04d558..724dc6cf710 100644 --- a/.github/workflows/mbedtls.yml +++ b/.github/workflows/mbedtls.yml @@ -14,6 +14,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION env: diff --git a/.github/workflows/membrowse-report.yml b/.github/workflows/membrowse-report.yml index e4dabc58a7e..f7308819cd0 100644 --- a/.github/workflows/membrowse-report.yml +++ b/.github/workflows/membrowse-report.yml @@ -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 diff --git a/.github/workflows/memcached.yml b/.github/workflows/memcached.yml index 7bd9b5b4e30..af98ac1ad9b 100644 --- a/.github/workflows/memcached.yml +++ b/.github/workflows/memcached.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/mono.yml b/.github/workflows/mono.yml index 45b2c01a3a3..36b632fde57 100644 --- a/.github/workflows/mono.yml +++ b/.github/workflows/mono.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/mosquitto.yml b/.github/workflows/mosquitto.yml index c960268383c..49b515d274b 100644 --- a/.github/workflows/mosquitto.yml +++ b/.github/workflows/mosquitto.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/msmtp.yml b/.github/workflows/msmtp.yml index ef02f75bdf0..1596a8da22e 100644 --- a/.github/workflows/msmtp.yml +++ b/.github/workflows/msmtp.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index e7a9644bb92..bc2ce930703 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/multi-arch.yml b/.github/workflows/multi-arch.yml index 0854c430d30..8de365c8578 100644 --- a/.github/workflows/multi-arch.yml +++ b/.github/workflows/multi-arch.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/multi-compiler.yml b/.github/workflows/multi-compiler.yml index 3dc86dd94eb..93fb49384bf 100644 --- a/.github/workflows/multi-compiler.yml +++ b/.github/workflows/multi-compiler.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/net-snmp.yml b/.github/workflows/net-snmp.yml index 58eca4edac6..78a0a6238a1 100644 --- a/.github/workflows/net-snmp.yml +++ b/.github/workflows/net-snmp.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/nginx.yml b/.github/workflows/nginx.yml index 65d70838e6c..faa160f6ec3 100644 --- a/.github/workflows/nginx.yml +++ b/.github/workflows/nginx.yml @@ -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 diff --git a/.github/workflows/no-malloc.yml b/.github/workflows/no-malloc.yml index 1d9ab065614..ac1f6650ef1 100644 --- a/.github/workflows/no-malloc.yml +++ b/.github/workflows/no-malloc.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/nss.yml b/.github/workflows/nss.yml index 338c9684414..a86e981d293 100644 --- a/.github/workflows/nss.yml +++ b/.github/workflows/nss.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION env: diff --git a/.github/workflows/ntp.yml b/.github/workflows/ntp.yml index 4cbe22b92c8..23e4b36a25a 100644 --- a/.github/workflows/ntp.yml +++ b/.github/workflows/ntp.yml @@ -14,6 +14,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/ocsp.yml b/.github/workflows/ocsp.yml index bd46e8212aa..861040ca599 100644 --- a/.github/workflows/ocsp.yml +++ b/.github/workflows/ocsp.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/openldap.yml b/.github/workflows/openldap.yml index cc5dcfc4ad6..e681022b990 100644 --- a/.github/workflows/openldap.yml +++ b/.github/workflows/openldap.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/openssh.yml b/.github/workflows/openssh.yml index 84f73eec23c..e512cca391a 100644 --- a/.github/workflows/openssh.yml +++ b/.github/workflows/openssh.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/openssl-ech.yml b/.github/workflows/openssl-ech.yml index 21dca0a71e6..b86167f7506 100644 --- a/.github/workflows/openssl-ech.yml +++ b/.github/workflows/openssl-ech.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/opensslcoexist.yml b/.github/workflows/opensslcoexist.yml index 6b0f48f7b6b..518b5ca168a 100644 --- a/.github/workflows/opensslcoexist.yml +++ b/.github/workflows/opensslcoexist.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/openvpn.yml b/.github/workflows/openvpn.yml index 644909654c5..c8773a9f6c4 100644 --- a/.github/workflows/openvpn.yml +++ b/.github/workflows/openvpn.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 5efaea93989..3fd87c01acd 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -27,6 +27,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index 5e62521a96c..7053ba755b4 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/pam-ipmi.yml b/.github/workflows/pam-ipmi.yml index 02a385a359e..de907d05aff 100644 --- a/.github/workflows/pam-ipmi.yml +++ b/.github/workflows/pam-ipmi.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION diff --git a/.github/workflows/pq-all.yml b/.github/workflows/pq-all.yml index 7805f91d876..c677c616fe1 100644 --- a/.github/workflows/pq-all.yml +++ b/.github/workflows/pq-all.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/pr-commit-check.yml b/.github/workflows/pr-commit-check.yml index 78449b7c996..faa8b8541d7 100644 --- a/.github/workflows/pr-commit-check.yml +++ b/.github/workflows/pr-commit-check.yml @@ -8,6 +8,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/psk.yml b/.github/workflows/psk.yml index 22c7de77df7..147f586c3fa 100644 --- a/.github/workflows/psk.yml +++ b/.github/workflows/psk.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/puf.yml b/.github/workflows/puf.yml index 737688bee20..0b760728b35 100644 --- a/.github/workflows/puf.yml +++ b/.github/workflows/puf.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index f43b1188a23..95d33be9965 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/rng-tools.yml b/.github/workflows/rng-tools.yml index 06fc6eb7616..1027ab80fc6 100644 --- a/.github/workflows/rng-tools.yml +++ b/.github/workflows/rng-tools.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/rtl8735b.yml b/.github/workflows/rtl8735b.yml index fe262749d15..2696cc29f73 100644 --- a/.github/workflows/rtl8735b.yml +++ b/.github/workflows/rtl8735b.yml @@ -15,6 +15,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/rust-wrapper.yml b/.github/workflows/rust-wrapper.yml index 1b97237616d..b95c21cfe84 100644 --- a/.github/workflows/rust-wrapper.yml +++ b/.github/workflows/rust-wrapper.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/smallStackSize.yml b/.github/workflows/smallStackSize.yml index fe07ad83ad3..636b8165d83 100644 --- a/.github/workflows/smallStackSize.yml +++ b/.github/workflows/smallStackSize.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/socat.yml b/.github/workflows/socat.yml index 6b285653d0b..2e26cf7f0d1 100644 --- a/.github/workflows/socat.yml +++ b/.github/workflows/socat.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/softhsm.yml b/.github/workflows/softhsm.yml index 9d141a2b082..aeb60ce2271 100644 --- a/.github/workflows/softhsm.yml +++ b/.github/workflows/softhsm.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/sssd.yml b/.github/workflows/sssd.yml index d3ba3667c6b..90d647c1112 100644 --- a/.github/workflows/sssd.yml +++ b/.github/workflows/sssd.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/stunnel.yml b/.github/workflows/stunnel.yml index 879bc1655c4..56ab4f26e93 100644 --- a/.github/workflows/stunnel.yml +++ b/.github/workflows/stunnel.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/symbol-prefixes.yml b/.github/workflows/symbol-prefixes.yml index fd767ca0092..214ba447341 100644 --- a/.github/workflows/symbol-prefixes.yml +++ b/.github/workflows/symbol-prefixes.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/threadx.yml b/.github/workflows/threadx.yml index aa44193af9c..5b4beb62d3e 100644 --- a/.github/workflows/threadx.yml +++ b/.github/workflows/threadx.yml @@ -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 }} diff --git a/.github/workflows/trackmemory.yml b/.github/workflows/trackmemory.yml index f30d93d5e25..e2cf5ddde1d 100644 --- a/.github/workflows/trackmemory.yml +++ b/.github/workflows/trackmemory.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/watcomc.yml b/.github/workflows/watcomc.yml index 3fa6063239b..af47d55223c 100644 --- a/.github/workflows/watcomc.yml +++ b/.github/workflows/watcomc.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/win-csharp-test.yml b/.github/workflows/win-csharp-test.yml index 001ac0fd96a..1ccdd82f023 100644 --- a/.github/workflows/win-csharp-test.yml +++ b/.github/workflows/win-csharp-test.yml @@ -7,6 +7,9 @@ on: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] +permissions: + contents: read + jobs: build: diff --git a/.github/workflows/windows-arm64.yml b/.github/workflows/windows-arm64.yml index 41627a43434..aae86f13d0f 100644 --- a/.github/workflows/windows-arm64.yml +++ b/.github/workflows/windows-arm64.yml @@ -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 diff --git a/.github/workflows/wolfCrypt-Wconversion.yml b/.github/workflows/wolfCrypt-Wconversion.yml index 6e608c53688..0002f3809c2 100644 --- a/.github/workflows/wolfCrypt-Wconversion.yml +++ b/.github/workflows/wolfCrypt-Wconversion.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/wolfboot-integration.yml b/.github/workflows/wolfboot-integration.yml index 47b44fafaec..8f4827f00c5 100644 --- a/.github/workflows/wolfboot-integration.yml +++ b/.github/workflows/wolfboot-integration.yml @@ -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 diff --git a/.github/workflows/wolfsm.yml b/.github/workflows/wolfsm.yml index 113e255a991..927a709f464 100644 --- a/.github/workflows/wolfsm.yml +++ b/.github/workflows/wolfsm.yml @@ -16,6 +16,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/xcode.yml b/.github/workflows/xcode.yml index e5b0254c9dc..e18cd2ea959 100644 --- a/.github/workflows/xcode.yml +++ b/.github/workflows/xcode.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/zephyr-4.x.yml b/.github/workflows/zephyr-4.x.yml index dd5543235a1..757020a789f 100644 --- a/.github/workflows/zephyr-4.x.yml +++ b/.github/workflows/zephyr-4.x.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index f0bb0fc7dee..c987502a842 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -11,6 +11,9 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +permissions: + contents: read # END OF COMMON SECTION jobs: