Skip to content
Open
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
51 changes: 51 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -16823,6 +16823,36 @@ static int GetPeerCertType(const WOLFSSL* ssl)
}
#endif /* HAVE_RPK */

#ifdef WOLFSSL_TRUST_PEER_CERT
/* Helper function to check peer certificate dates since the standard
* checks and parsing are skipped for trusted peer certificates. */
static int CheckTrustedPeerDates(DecodedCert* cert)
{
if (cert == NULL)
return BAD_FUNC_ARG;

#ifndef NO_ASN_TIME
if (wc_AsnGetSkipDateCheck())
return 0;

if ((cert->beforeDate != NULL) && (cert->beforeDateLen > 2) &&
(wc_ValidateDate(&cert->beforeDate[2], cert->beforeDate[0],
ASN_BEFORE, cert->beforeDate[1]) == 0)) {
Comment on lines +16839 to +16840
WOLFSSL_MSG("Trusted peer cert is not yet valid");
return ASN_BEFORE_DATE_E;
}

if ((cert->afterDate != NULL) && (cert->afterDateLen > 2) &&
(wc_ValidateDate(&cert->afterDate[2], cert->afterDate[0],
ASN_AFTER, cert->afterDate[1]) == 0)) {
WOLFSSL_MSG("Trusted peer cert has expired");
return ASN_AFTER_DATE_E;
}
#endif
return 0;
}
#endif /* WOLFSSL_TRUST_PEER_CERT */

static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args,
int certType, int verify, byte** pSubjectHash, int* pAlreadySigner)
{
Expand Down Expand Up @@ -18495,6 +18525,27 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,

if (tp) {
WOLFSSL_MSG("Found matching trusted peer cert");
ret = CheckTrustedPeerDates(args->dCert);
if (ret != 0) {
#if defined(OPENSSL_EXTRA) || \
defined(OPENSSL_EXTRA_X509_SMALL)
/* report as the chain path would have */
if (ssl->peerVerifyRet == 0) {
if (ret ==
WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) {
ssl->peerVerifyRet = (unsigned long)
WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID;
}
else if (ret ==
WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) {
ssl->peerVerifyRet = (unsigned long)
WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED;
}
}
#endif
WOLFSSL_ERROR_VERBOSE(ret);
goto exit_ppc;
Comment on lines +18546 to +18547
}
args->haveTrustPeer = 1;
}
else {
Expand Down
54 changes: 54 additions & 0 deletions tests/api/test_certman.c
Original file line number Diff line number Diff line change
Expand Up @@ -4203,3 +4203,57 @@ int test_wolfSSL_CertManagerNameConstraint_skid_disambiguates(void)
#endif
return EXPECT_RESULT();
}

/* A certificate loaded as a trusted peer must still be subject to its own
* validity period. The trusted peer match skips chain processing, so the
* date check that the chain would have applied has to be made on that path
* as well; without it an expired pinned certificate is accepted. */
int test_wolfSSL_trust_peer_cert_expired(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TRUST_PEER_CERT) && !defined(NO_ASN_TIME) && \
!defined(NO_RSA) && !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \
defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES)
test_ssl_cbf client_cb;
test_ssl_cbf server_cb;
int ret;

XMEMSET(&client_cb, 0, sizeof(client_cb));
XMEMSET(&server_cb, 0, sizeof(server_cb));

/* the server presents a certificate that expired in 2018 */
server_cb.certPemFile = "certs/test/expired/expired-cert.pem";
server_cb.keyPemFile = "certs/server-key.pem";

client_cb.ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
ExpectNotNull(client_cb.ctx);
client_cb.isSharedCtx = 1;

/* The client pins that same expired certificate and loads no CA, so a
* trusted peer match is the only way the handshake could succeed.
*
* Whether the certificate can be loaded at all depends on the build:
* where WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS carries
* WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY the store takes it and the date has
* to be applied during the handshake, which is what this covers.
* Elsewhere the load itself refuses it, which is an equally good
* refusal. Either way the expired certificate must not authenticate a
* peer. */
ret = wolfSSL_CTX_trust_peer_cert(client_cb.ctx,
"certs/test/expired/expired-cert.pem", WOLFSSL_FILETYPE_PEM);
if (ret == WOLFSSL_SUCCESS) {
wolfSSL_CTX_set_verify(client_cb.ctx, WOLFSSL_VERIFY_PEER, NULL);

/* the pin must not revive an expired certificate */
ExpectIntNE(test_wolfSSL_client_server_nofail_memio(&client_cb,
&server_cb, NULL), TEST_SUCCESS);
ExpectIntEQ(client_cb.last_err, WC_NO_ERR_TRACE(ASN_AFTER_DATE_E));
}
else {
ExpectIntEQ(ret, WC_NO_ERR_TRACE(ASN_AFTER_DATE_E));
}
Comment on lines +4242 to +4254

wolfSSL_CTX_free(client_cb.ctx);
#endif
return EXPECT_RESULT();
}
4 changes: 3 additions & 1 deletion tests/api/test_certman.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <tests/api/api_decl.h>

int test_wolfSSL_CertManagerAPI(void);
int test_wolfSSL_trust_peer_cert_expired(void);
int test_wolfSSL_CertManagerLoadCABuffer(void);
int test_wolfSSL_CertManagerLoadCABuffer_ex(void);
int test_wolfSSL_CertManagerLoadCABufferType(void);
Expand Down Expand Up @@ -107,6 +108,7 @@ int test_wolfSSL_CertManagerNameConstraint_skid_disambiguates(void);
TEST_DECL_GROUP("certman", \
test_wolfSSL_CertManagerNameConstraint_valid_chain), \
TEST_DECL_GROUP("certman", \
test_wolfSSL_CertManagerNameConstraint_skid_disambiguates)
test_wolfSSL_CertManagerNameConstraint_skid_disambiguates), \
TEST_DECL_GROUP("certman", test_wolfSSL_trust_peer_cert_expired)

#endif /* WOLFCRYPT_TEST_CERTMAN_H */
Loading