Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,6 @@ WOLFSSL_NO_DH186
WOLFSSL_NO_DTLS_SIZE_CHECK
WOLFSSL_NO_ETM_ALERT
WOLFSSL_NO_FENCE
WOLFSSL_NO_INIT_CTX_KEY
WOLFSSL_NO_ISSUERHASH_TDPEER
WOLFSSL_NO_KCAPI_AES_CBC
WOLFSSL_NO_KCAPI_HMAC_SHA1
Expand Down
35 changes: 27 additions & 8 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,7 @@ then
AC_MSG_ERROR([--enable-all-osp is incompatible with --enable-linuxkm-defaults])
fi

test "$enable_tailscale" = "" && enable_tailscale=yes
Comment thread
lealem47 marked this conversation as resolved.
test "$enable_wolfguard" = "" && enable_wolfguard=yes
test "$enable_webserver" = "" && enable_webserver=yes

Expand Down Expand Up @@ -1648,6 +1649,30 @@ then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT"
fi

# Support for Tailscale port
AC_ARG_ENABLE([tailscale],
[AS_HELP_STRING([--enable-tailscale],[Enable Tailscale build dependencies (default: disabled)])],
[ ENABLED_TAILSCALE=$enableval ],
[ ENABLED_TAILSCALE=no ]
)
if test "$ENABLED_TAILSCALE" = "yes"
then
enable_wolfguard=yes
test "x$enable_sp" = "x" && enable_sp="yes,256"
enable_opensslall=yes
enable_alpn=yes
enable_sni=yes
enable_certgen=yes
enable_certreq=yes
enable_certext=yes
enable_sessioncerts=yes
enable_cert_setup_cb=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PUBLIC_MP"
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_INIT_CTX_KEY"
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI"
AM_CFLAGS="$AM_CFLAGS -DWC_CTC_NAME_SIZE=128 -DWOLFSSL_ACME_OID"
fi
Comment thread
lealem47 marked this conversation as resolved.

# wolfGuard
AC_ARG_ENABLE([wolfguard],
[AS_HELP_STRING([--enable-wolfguard],[Enable wolfGuard dependencies (default: disabled)])],
Expand All @@ -1661,9 +1686,9 @@ then
test "$enable_aesgcm" = "" && enable_aesgcm=yes
test "$enable_base64encode" = "" && enable_base64encode=yes
test "$enable_base16" = "" && enable_base16=yes
test "$enable_compkey" = "" && enable_compkey=yes
if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -ge 6
then
test "$enable_compkey" = "" && enable_compkey=yes
test "$enable_aesgcm_stream" = "" && enable_aesgcm_stream=yes
fi
fi
Expand Down Expand Up @@ -4912,8 +4937,7 @@ AC_ARG_ENABLE([compkey],
[ ENABLED_COMPKEY=no ]
)

if (test "$ENABLED_WPAS" = "yes" || test "$ENABLED_OPENSSLALL" = "yes") &&
(test "$HAVE_FIPS_VERSION" != "5")
if (test "$ENABLED_WPAS" = "yes" || test "$ENABLED_OPENSSLALL" = "yes")
then
ENABLED_COMPKEY=yes
fi
Expand Down Expand Up @@ -6810,11 +6834,6 @@ AS_CASE([$FIPS_VERSION],
(test "$FIPS_VERSION" != "v5-dev" || test "$enable_keygen" != "no")],
[ENABLED_KEYGEN="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN"])

AS_IF([test "$ENABLED_COMPKEY" = "yes" &&
! (test "$FIPS_VERSION" = "v5-dev" && test "$enable_compkey" = "yes")],
[AC_MSG_WARN([Forcing off compkey for FIPS ${FIPS_VERSION}.])
ENABLED_COMPKEY="no"])

AS_IF([test "$ENABLED_SHA224" != "yes" &&
(test "$FIPS_VERSION" != "v5-dev" || test "$enable_sha224" != "no")],
[ENABLED_SHA224="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224"])
Expand Down
85 changes: 85 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -11626,6 +11626,90 @@ static int test_wolfSSL_mcast(void)
| Wolfcrypt
*----------------------------------------------------------------------------*/

/*
* Testing wc_SetAcmeIdentifierExt() round-trip - the RFC 8737
* id-pe-acmeIdentifier (1.3.6.1.5.5.7.1.31) extension used by
* TLS-ALPN-01 ACME challenge certs.
*/
static int test_wc_SetAcmeIdentifierExt(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_ACME_OID) && defined(WOLFSSL_CERT_GEN) && \
defined(HAVE_ECC) && !defined(NO_SHA256) && !defined(NO_ASN_TIME) && \
!defined(WC_NO_RNG) && !defined(NO_RSA)
Cert cert;
DecodedCert decoded;
WC_RNG rng;
ecc_key key;
byte der[TWOK_BUF];
int derSz = 0;
int rngInited = 0, keyInited = 0;
const char* keyAuth = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
".kZdq0qaDcXNVxKBkP_uiKvw2Yg5sRJ8KBfQa9Ru13nE";
word32 keyAuthSz = (word32)XSTRLEN(keyAuth);
byte expected[WC_SHA256_DIGEST_SIZE];

XMEMSET(&cert, 0, sizeof(cert));
XMEMSET(&decoded, 0, sizeof(decoded));
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(&key, 0, sizeof(key));
XMEMSET(der, 0, sizeof(der));

/* Compute the expected digest */
ExpectIntEQ(wc_Sha256Hash((const byte*)keyAuth, keyAuthSz, expected), 0);

/* Input validation. */
ExpectIntEQ(wc_SetAcmeIdentifierExt(NULL, (const byte*)keyAuth, keyAuthSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_SetAcmeIdentifierExt(&cert, NULL, keyAuthSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_SetAcmeIdentifierExt(&cert, (const byte*)keyAuth, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));

/* Build a P-256 keypair to sign the cert. */
ExpectIntEQ(wc_InitRng(&rng), 0);
rngInited = 1;
ExpectIntEQ(wc_ecc_init(&key), 0);
keyInited = 1;
ExpectIntEQ(wc_ecc_make_key_ex(&rng, KEY32, &key, ECC_SECP256R1), 0);

/* Build a minimal self-signed cert template carrying the extension. */
ExpectIntEQ(wc_InitCert(&cert), 0);
cert.sigType = CTC_SHA256wECDSA;
cert.daysValid = 1;
cert.isCA = 0;
XSTRNCPY(cert.subject.commonName, "acme-test.example", CTC_NAME_SIZE);

ExpectIntEQ(wc_SetAcmeIdentifierExt(&cert, (const byte*)keyAuth,
keyAuthSz), 0);
ExpectIntEQ(cert.acmeIdentifierSz, WC_SHA256_DIGEST_SIZE);
ExpectIntEQ(XMEMCMP(cert.acmeIdentifier, expected,
WC_SHA256_DIGEST_SIZE), 0);

/* MakeCert + SignCert. ECC_TYPE selects the ECDSA signing path. */
ExpectIntGT(derSz = wc_MakeCert_ex(&cert, der, sizeof(der),
ECC_TYPE, &key, &rng), 0);
ExpectIntGT(derSz = wc_SignCert_ex(cert.bodySz, cert.sigType,
der, sizeof(der),
ECC_TYPE, &key, &rng), 0);

/* Parse the cert back and verify the extension survives the
* round-trip via DecodeAcmeId. */
wc_InitDecodedCert(&decoded, der, derSz, NULL);
ExpectIntEQ(wc_ParseCert(&decoded, CERT_TYPE, NO_VERIFY, NULL), 0);
ExpectIntEQ(decoded.extAcmeIdentifierSet, 1);
ExpectIntEQ(decoded.extAcmeIdentifierCrit, 1);
ExpectIntEQ(decoded.acmeIdentifierSz, WC_SHA256_DIGEST_SIZE);
ExpectIntEQ(XMEMCMP(decoded.acmeIdentifier, expected,
WC_SHA256_DIGEST_SIZE), 0);

wc_FreeDecodedCert(&decoded);
if (keyInited) wc_ecc_free(&key);
if (rngInited) wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
} /* END test_wc_SetAcmeIdentifierExt */

/*
* Testing wc_SetKeyUsage()
*/
Expand Down Expand Up @@ -37017,6 +37101,7 @@ TEST_CASE testCases[] = {
#ifdef WOLFSSL_CERT_SIGN_CB
TEST_DECL(test_wc_SignCert_cb),
#endif
TEST_DECL(test_wc_SetAcmeIdentifierExt),
TEST_DECL(test_wc_SetKeyUsage),
TEST_DECL(test_wc_SetAuthKeyIdFromPublicKey_ex),
TEST_DECL(test_wc_SetSubjectBuffer),
Expand Down
114 changes: 114 additions & 0 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -19014,6 +19014,39 @@ static int DecodeKeyUsageInternal(const byte* input, word32 sz,
return DecodeKeyUsage(input, sz, &cert->extKeyUsage);
}

#ifdef WOLFSSL_ACME_OID
/* Decodes the RFC 8737 id-pe-acmeIdentifier (1.3.6.1.5.5.7.1.31)
* extension value into cert->acmeIdentifier.
*
* The extnValue is an OCTET STRING wrapping a SHA-256 digest of the
* ACME keyAuth, per RFC 8737 3. Length is verified against
* WC_SHA256_DIGEST_SIZE.
*
* @param [in] input ASN.1 DER-encoded extension value.
* @param [in] sz Length of input in bytes.
* @param [in, out] cert DecodedCert to populate (acmeIdentifier and
* acmeIdentifierSz fields).
*
* @return 0 on success.
* @return ASN_PARSE_E when the inner OCTET STRING is missing or not
* exactly WC_SHA256_DIGEST_SIZE bytes.
*/
static int DecodeAcmeId(const byte* input, word32 sz, DecodedCert* cert)
{
word32 hashIdx = 0;
int hashLen = 0;

if (GetOctetString(input, &hashIdx, &hashLen, sz) < 0)
return ASN_PARSE_E;
if (hashLen != WC_SHA256_DIGEST_SIZE)
return ASN_PARSE_E;

XMEMCPY(cert->acmeIdentifier, &input[hashIdx], WC_SHA256_DIGEST_SIZE);
cert->acmeIdentifierSz = WC_SHA256_DIGEST_SIZE;
return 0;
}
#endif /* WOLFSSL_ACME_OID */

#ifdef WOLFSSL_ASN_TEMPLATE
/* ASN.1 template for KeyPurposeId.
* X.509: RFC 5280, 4.2.1.12 - Extended Key Usage.
Expand Down Expand Up @@ -20236,6 +20269,14 @@ int DecodeExtensionType(const byte* input, word32 length, word32 oid,
return ASN_PARSE_E;
break;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifdef WOLFSSL_ACME_OID
case ACME_IDENTIFIER_OID:
VERIFY_AND_SET_OID(cert->extAcmeIdentifierSet);
cert->extAcmeIdentifierCrit = critical ? 1 : 0;
if (DecodeAcmeId(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
#endif
default:
if (isUnknownExt != NULL)
*isUnknownExt = 1;
Expand Down Expand Up @@ -25250,6 +25291,9 @@ typedef struct DerCert {
#endif
byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */
byte crlInfo[CTC_MAX_CRLINFO_SZ]; /* CRL Distribution Points */
#ifdef WOLFSSL_ACME_OID
byte acmeId[MAX_ACMEID_SZ]; /* RFC 8737 id-pe-acmeIdentifier */
#endif
#endif
#ifdef WOLFSSL_CERT_REQ
byte attrib[MAX_ATTRIB_SZ]; /* Cert req attributes encoded */
Expand Down Expand Up @@ -25280,6 +25324,9 @@ typedef struct DerCert {
#endif
int certPoliciesSz; /* encoded CertPolicies extension length*/
int crlInfoSz; /* encoded CRL Dist Points length */
#ifdef WOLFSSL_ACME_OID
int acmeIdSz; /* encoded acmeIdentifier length */
#endif
#endif
#ifdef WOLFSSL_ALT_NAMES
int altNamesSz; /* encoded AltNames extension length */
Expand Down Expand Up @@ -26510,6 +26557,12 @@ static const ASNItem static_certExtsASN[] = {
/* CRLINFO_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* CRLINFO_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* CRLINFO_STR */ { 1, ASN_OCTET_STRING, 0, 0, 0 },
/* RFC 8737 id-pe-acmeIdentifier */
/* ACMEID_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* ACMEID_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* ACMEID_CRIT */ { 1, ASN_BOOLEAN, 0, 0, 0 },
/* ACMEID_STR */ { 1, ASN_OCTET_STRING, 0, 1, 0 },
/* ACMEID_HASH */ { 2, ASN_OCTET_STRING, 0, 0, 0 },
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* SAPKI_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* SAPKI_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
Expand Down Expand Up @@ -26568,6 +26621,11 @@ enum {
CERTEXTSASN_IDX_CRLINFO_SEQ,
CERTEXTSASN_IDX_CRLINFO_OID,
CERTEXTSASN_IDX_CRLINFO_STR,
CERTEXTSASN_IDX_ACMEID_SEQ,
CERTEXTSASN_IDX_ACMEID_OID,
CERTEXTSASN_IDX_ACMEID_CRIT,
CERTEXTSASN_IDX_ACMEID_STR,
CERTEXTSASN_IDX_ACMEID_HASH,
#ifdef WOLFSSL_DUAL_ALG_CERTS
CERTEXTSASN_IDX_SAPKI_SEQ,
CERTEXTSASN_IDX_SAPKI_OID,
Expand Down Expand Up @@ -26623,6 +26681,10 @@ static int EncodeExtensions(Cert* cert, byte* output, word32 maxSz,
static const byte nsCertOID[] = { 0x60, 0x86, 0x48, 0x01,
0x86, 0xF8, 0x42, 0x01, 0x01 };
static const byte crlInfoOID[] = { 0x55, 0x1D, 0x1F };
#ifdef WOLFSSL_ACME_OID
static const byte acmeIdOID[] = { 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07,
0x01, 0x1F };
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
static const byte sapkiOID[] = { 0x55, 0x1d, 0x48 };
static const byte altSigAlgOID[] = { 0x55, 0x1d, 0x49 };
Expand Down Expand Up @@ -26878,6 +26940,24 @@ static int EncodeExtensions(Cert* cert, byte* output, word32 maxSz,
CERTEXTSASN_IDX_CRLINFO_STR);
}

#ifdef WOLFSSL_ACME_OID
/* id-pe-acmeIdentifier (TLS-ALPN-01 challenge cert).
* Always critical=TRUE. */
if (cert->acmeIdentifierSz == WC_SHA256_DIGEST_SIZE) {
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_ACMEID_OID],
acmeIdOID, sizeof(acmeIdOID));
SetASN_Boolean(&dataASN[CERTEXTSASN_IDX_ACMEID_CRIT], 1);
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_ACMEID_HASH],
cert->acmeIdentifier, (word32)cert->acmeIdentifierSz);
}
else
#endif /* WOLFSSL_ACME_OID */
{
/* Don't write out the ACME identifier extension. */
SetASNItem_NoOut(dataASN, CERTEXTSASN_IDX_ACMEID_SEQ,
CERTEXTSASN_IDX_ACMEID_HASH);
}

#ifdef WOLFSSL_DUAL_ALG_CERTS
if (cert->sapkiDer != NULL) {
/* Set subject alternative public key info OID, criticality and
Expand Down Expand Up @@ -29313,6 +29393,40 @@ int wc_SetExtKeyUsage(Cert *cert, const char *value)
return ret;
}

#ifdef WOLFSSL_ACME_OID
/* Set the id-pe-acmeIdentifier extension value from the ACME
* keyAuth string. Computes SHA-256 over keyAuth and stores the digest
* as the extension value. RFC 8737 3 requires critical=TRUE; that's
* applied at encode time in EncodeExtensions.
*
* keyAuth is the raw bytes of the key authorization string per
* RFC 8555 8.1: token "." JWK_thumbprint.
*/
int wc_SetAcmeIdentifierExt(Cert *cert, const byte *keyAuth, word32 keyAuthSz)
{
int ret;
byte digest[WC_SHA256_DIGEST_SIZE];
wc_Sha256 sha;

if (cert == NULL || keyAuth == NULL || keyAuthSz == 0)
return BAD_FUNC_ARG;

ret = wc_InitSha256(&sha);
if (ret != 0)
return ret;
ret = wc_Sha256Update(&sha, keyAuth, keyAuthSz);
if (ret == 0)
ret = wc_Sha256Final(&sha, digest);
wc_Sha256Free(&sha);
if (ret != 0)
return ret;

XMEMCPY(cert->acmeIdentifier, digest, WC_SHA256_DIGEST_SIZE);
cert->acmeIdentifierSz = WC_SHA256_DIGEST_SIZE;
return 0;
}
#endif /* WOLFSSL_ACME_OID */

#ifdef WOLFSSL_EKU_OID
/*
* cert structure to set EKU oid in
Expand Down
Loading
Loading