Merge pull request #4948 from SparkiDev/tls12_pa_failsafe

TLS: add peer authentication failsafe for TLS 1.2 and below
pull/4957/head
David Garske 2022-03-15 09:42:56 -07:00 committed by GitHub
commit 9c29102c43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 167 additions and 17 deletions

View File

@ -4470,7 +4470,7 @@ then
fi
if test "$ENABLED_TLS13_EARLY_DATA" = "yes"
then
if test "x$ENABLED_TLS13" = "xno"
if test "x$ENABLED_TLS13" = "xno" && test "X$ENABLED_ALL" = "xno"
then
AC_MSG_ERROR([cannot enable earlydata without enabling tls13.])
fi
@ -4478,8 +4478,11 @@ then
then
AC_MSG_ERROR([cannot enable earlydata without enabling session tickets and/or PSK.])
fi
if test "x$ENABLED_TLS13" = "xyes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_EARLY_DATA"
fi
fi
if test "$ENABLED_TLSV12" = "no" && test "$ENABLED_TLS13" = "yes" && test "x$ENABLED_SESSION_TICKET" = "xno"
then

View File

@ -12766,7 +12766,23 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
goto exit_ppc;
}
/* Certificate validated and stored. */
ssl->options.havePeerCert = 1;
#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_RSA)
if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->specs.sig_algo == rsa_kea) {
/* CLIENT: No ServerKeyExchange message sent by server. */
ssl->options.peerAuthGood = 1;
}
#endif
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_ECC)
if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->specs.static_ecdh) {
/* CLIENT: No ServerKeyExchange message sent by server. */
ssl->options.peerAuthGood = 1;
}
#endif
if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
#ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
@ -14274,6 +14290,8 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->options.resuming) {
WOLFSSL_MSG("Not resuming as thought");
ssl->options.resuming = 0;
/* CLIENT: No longer resuming, reset peer authentication state. */
ssl->options.peerAuthGood = 0;
}
break;
@ -21915,9 +21933,10 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
ssl->suites->sigAlgo = ssl->buffers.keyType;
#endif
}
else
else {
ssl->suites->sigAlgo = ssl->specs.sig_algo;
if (ssl->suites->sigAlgo == 0) {
}
if (ssl->suites->sigAlgo == anonymous_sa_algo) {
/* PSK ciphersuite - get digest to use from cipher suite */
ssl->suites->hashAlgo = ssl->specs.mac_algorithm;
return 0;
@ -23459,6 +23478,8 @@ exit_dpk:
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
#endif /* NO_OLD_TLS */
/* SERVER: peer auth based on session secret. */
ssl->options.peerAuthGood = (ret == 0);
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
return ret;
@ -24812,6 +24833,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
(void**)&ssl->peerEccDsaKey);
ssl->peerEccDsaKeyPresent = 0;
}
/* CLIENT: Data verified with cert's public key. */
ssl->options.peerAuthGood =
ssl->options.havePeerCert && (ret == 0);
break;
}
#endif /* HAVE_ECC */
@ -24839,6 +24863,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
(void**)&ssl->peerEd25519Key);
ssl->peerEd25519KeyPresent = 0;
}
/* CLIENT: Data verified with cert's public key. */
ssl->options.peerAuthGood =
ssl->options.havePeerCert && (ret == 0);
break;
}
#endif /* HAVE_ED25519 */
@ -24866,6 +24893,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
(void**)&ssl->peerEd448Key);
ssl->peerEd448KeyPresent = 0;
}
/* CLIENT: Data verified with cert's public key. */
ssl->options.peerAuthGood =
ssl->options.havePeerCert && (ret == 0);
break;
}
#endif /* HAVE_ED448 */
@ -24937,6 +24967,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
#endif
if (ret != 0)
return ret;
/* CLIENT: Data verified with cert's public key. */
ssl->options.peerAuthGood =
ssl->options.havePeerCert;
break;
#endif
case rsa_sa_algo:
@ -24989,6 +25022,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
FINISHED_SZ) != 0) {
ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske);
}
/* CLIENT: Data verified with cert's public key. */
ssl->options.peerAuthGood =
ssl->options.havePeerCert;
break;
}
#endif /* !NO_RSA */
@ -25526,6 +25562,8 @@ int SendClientKeyExchange(WOLFSSL* ssl)
}
XMEMCPY(args->encSecret, ssl->arrays->client_identity,
args->encSz);
/* CLIENT: Pre-shared Key for peer authentication. */
ssl->options.peerAuthGood = 1;
/* make psk pre master secret */
/* length of key + length 0s + length of key + key */
@ -25562,6 +25600,8 @@ int SendClientKeyExchange(WOLFSSL* ssl)
if (esSz > MAX_PSK_ID_LEN) {
ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
}
/* CLIENT: Pre-shared Key for peer authentication. */
ssl->options.peerAuthGood = 1;
ssl->buffers.sig.length = ENCRYPT_LEN;
ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
@ -25640,6 +25680,8 @@ int SendClientKeyExchange(WOLFSSL* ssl)
if (esSz > MAX_PSK_ID_LEN) {
ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
}
/* CLIENT: Pre-shared Key for peer authentication. */
ssl->options.peerAuthGood = 1;
/* place size and identity in output buffer sz:identity */
c16toa((word16)esSz, args->output);
@ -29218,6 +29260,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
#endif
/* SERVER: peer auth based on session secret. */
ssl->options.peerAuthGood = (ret == 0);
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
return ret;
@ -29341,10 +29385,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
#endif
/* SERVER: peer auth based on session secret. */
ssl->options.peerAuthGood = (ret == 0);
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
}
}
return ret;
}
@ -30203,6 +30250,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
NULL
#endif
);
/* SERVER: Data verified with certificate's public key. */
ssl->options.peerAuthGood = ssl->options.havePeerCert &&
(ret == 0);
}
#endif /* HAVE_ECC */
#if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
@ -30219,6 +30269,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
NULL
#endif
);
/* SERVER: Data verified with certificate's public key. */
ssl->options.peerAuthGood = ssl->options.havePeerCert &&
(ret == 0);
}
#endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
#if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
@ -30235,6 +30288,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
NULL
#endif
);
/* SERVER: Data verified with certificate's public key. */
ssl->options.peerAuthGood = ssl->options.havePeerCert &&
(ret == 0);
}
#endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
@ -30315,7 +30371,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
XFREE(encodedSig, ssl->heap,
DYNAMIC_TYPE_SIGNATURE);
#endif
}
}
@ -30326,8 +30383,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ret = VERIFY_CERT_ERROR;
}
}
if (ret == 0) {
/* SERVER: Data verified with cert's public key. */
ssl->options.peerAuthGood = ssl->options.havePeerCert &&
(ret == 0);
}
}
#endif /* !NO_RSA */
if (ret != 0)
break;
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_FINALIZE;
@ -31820,6 +31884,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
#endif
ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
}
/* SERVER: Pre-shared Key for peer authentication. */
ssl->options.peerAuthGood = 1;
/* make psk pre master secret */
/* length of key + length 0s + length of key + key */
@ -32659,6 +32725,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
#endif
ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
}
/* SERVER: Pre-shared Key for peer authentication. */
ssl->options.peerAuthGood = 1;
c16toa((word16) ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;
@ -32695,6 +32763,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
}
/* SERVER: Pre-shared Key for peer authentication. */
ssl->options.peerAuthGood = 1;
c16toa((word16) ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;

View File

@ -2064,6 +2064,11 @@ int SetCipherSpecs(WOLFSSL* ssl)
#endif
#endif
if (ssl->specs.sig_algo == anonymous_sa_algo) {
/* CLIENT/SERVER: No peer authentication to be performed. */
ssl->options.peerAuthGood = 1;
}
return 0;
}

View File

@ -3168,6 +3168,8 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl)
ret = wolfSSL_UseSessionTicket(ssl);
#endif
}
/* CLIENT/SERVER: Reset peer authentication for full secure handshake. */
ssl->options.peerAuthGood = 0;
#ifdef HAVE_SESSION_TICKET
if (ret == WOLFSSL_SUCCESS)
@ -14611,6 +14613,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
case FIRST_REPLY_SECOND :
/* CLIENT: Fail-safe for Server Authentication. */
if (!ssl->options.peerAuthGood) {
WOLFSSL_MSG("Server authentication did not happen");
return WOLFSSL_FATAL_ERROR;
}
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
if (ssl->options.sendVerify) {
if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
@ -15007,6 +15015,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
return WOLFSSL_FATAL_ERROR;
}
}
else {
/* SERVER: Peer auth good if not verifying client. */
ssl->options.peerAuthGood = 1;
}
}
#endif
ssl->options.acceptState = CERT_REQ_SENT;
@ -15036,6 +15048,21 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case ACCEPT_SECOND_REPLY_DONE :
#ifndef NO_CERTS
/* SERVER: When not resuming and verifying peer but no certificate
* received and not failing when not received then peer auth good.
*/
if (!ssl->options.resuming && ssl->options.verifyPeer &&
!ssl->options.havePeerCert && !ssl->options.failNoCert) {
ssl->options.peerAuthGood = 1;
}
#endif /* !NO_CERTS */
#ifdef WOLFSSL_NO_CLIENT_AUTH
if (!ssl->options.resuming) {
ssl->options.peerAuthGood = 1;
}
#endif
#ifdef HAVE_SESSION_TICKET
if (ssl->options.createTicket && !ssl->options.noTicketTls12) {
if ( (ssl->error = SendTicket(ssl)) != 0) {
@ -15049,6 +15076,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case TICKET_SENT:
/* SERVER: Fail-safe for CLient Authentication. */
if (!ssl->options.peerAuthGood) {
WOLFSSL_MSG("Client authentication did not happen");
return WOLFSSL_FATAL_ERROR;
}
if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;

View File

@ -5149,6 +5149,8 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, const byte* input,
WOLFSSL_MSG("Using existing client ticket");
ssl->options.useTicket = 1;
ssl->options.resuming = 1;
/* SERVER: ticket is peer auth. */
ssl->options.peerAuthGood = 1;
} else if (ret == WOLFSSL_TICKET_RET_CREATE) {
WOLFSSL_MSG("Using existing client ticket, creating new one");
ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
@ -5159,6 +5161,8 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, const byte* input,
ssl->options.createTicket = 1; /* will send ticket msg */
ssl->options.useTicket = 1;
ssl->options.resuming = 1;
/* SERVER: ticket is peer auth. */
ssl->options.peerAuthGood = 1;
}
} else if (ret == WOLFSSL_TICKET_RET_REJECT) {
WOLFSSL_MSG("Process client ticket rejected, not using");

View File

@ -2781,6 +2781,10 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello)
ssl->session->ticketNonce.len, ssl->arrays->psk_key)) != 0) {
return ret;
}
if (!clientHello) {
/* CLIENT: using secret in ticket for peer authentication. */
ssl->options.peerAuthGood = 1;
}
}
#endif
#ifndef NO_PSK
@ -2903,6 +2907,11 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello)
psk->cipherSuite != suite[1])) {
return PSK_KEY_ERROR;
}
if (!clientHello) {
/* CLIENT: using PSK for peer authentication. */
ssl->options.peerAuthGood = 1;
}
}
#endif
@ -3629,7 +3638,6 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if ((ret = SetupPskKey(ssl, psk, 0)) != 0)
return ret;
ssl->options.pskNegotiated = 1;
ssl->options.peerAuthGood = 1;
}
#endif
@ -3961,6 +3969,8 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err)
if ((ret == 0) && found) {
/* PSK negotiation has succeeded */
ssl->options.isPSK = 1;
/* SERVER: using PSK for peer authentication. */
ssl->options.peerAuthGood = 1;
}
}
@ -4055,6 +4065,9 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first)
}
#endif
/* SERVER: using secret in session ticket for peer auth. */
ssl->options.peerAuthGood = 1;
#ifdef WOLFSSL_EARLY_DATA
ssl->options.maxEarlyDataSz = ssl->session->maxEarlyDataSz;
#endif
@ -4894,7 +4907,6 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
ssl->options.pskNegotiated = (args->usingPSK != 0);
ssl->options.peerAuthGood = ssl->options.pskNegotiated;
#endif
if (!args->usingPSK) {
@ -6744,6 +6756,9 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
);
if (ret >= 0) {
/* CLIENT/SERVER: data verified with public key from
* certificate. */
ssl->options.peerAuthGood = 1;
FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
ssl->peerEccDsaKeyPresent = 0;
}
@ -6762,6 +6777,9 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
);
if (ret >= 0) {
/* CLIENT/SERVER: data verified with public key from
* certificate. */
ssl->options.peerAuthGood = 1;
FreeKey(ssl, DYNAMIC_TYPE_ED25519,
(void**)&ssl->peerEd25519Key);
ssl->peerEd25519KeyPresent = 0;
@ -6781,6 +6799,9 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
);
if (ret >= 0) {
/* CLIENT/SERVER: data verified with public key from
* certificate. */
ssl->options.peerAuthGood = 1;
FreeKey(ssl, DYNAMIC_TYPE_ED448,
(void**)&ssl->peerEd448Key);
ssl->peerEd448KeyPresent = 0;
@ -6796,6 +6817,9 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
&res, ssl->peerFalconKey);
if ((ret >= 0) && (res == 1)) {
/* CLIENT/SERVER: data verified with public key from
* certificate. */
ssl->options.peerAuthGood = 1;
FreeKey(ssl, DYNAMIC_TYPE_FALCON,
(void**)&ssl->peerFalconKey);
ssl->peerFalconKeyPresent = 0;
@ -6822,8 +6846,11 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
if (ret != 0)
goto exit_dcv;
FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
/* CLIENT/SERVER: data verified with public key from
* certificate. */
ssl->peerRsaKeyPresent = 0;
FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
ssl->options.peerAuthGood = 1;
}
#endif /* !NO_RSA && WC_RSA_PSS */
@ -6835,7 +6862,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
case TLS_ASYNC_FINALIZE:
{
ssl->options.havePeerVerify = 1;
ssl->options.peerAuthGood = 1;
/* Set final index */
args->idx += args->sz;
@ -7965,10 +7991,6 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_certificate = 1;
if (ssl->options.side == WOLFSSL_SERVER_END &&
(!ssl->options.verifyPeer || !ssl->options.failNoCert)) {
ssl->options.peerAuthGood = 1;
}
break;
@ -8732,6 +8754,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
FALL_THROUGH;
case FIRST_REPLY_SECOND:
/* CLIENT: check peer authentication. */
if (!ssl->options.peerAuthGood) {
WOLFSSL_MSG("Server authentication did not happen");
return WOLFSSL_FATAL_ERROR;
@ -9683,6 +9706,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
}
}
else {
/* SERVER: Peer auth good if not verifying client. */
ssl->options.peerAuthGood = 1;
}
}
@ -9763,6 +9787,17 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
FALL_THROUGH;
case TLS13_ACCEPT_FINISHED_DONE :
/* SERVER: When not resuming and verifying peer but no certificate
* received and not failing when not received then peer auth good.
*/
if (!ssl->options.resuming && ssl->options.verifyPeer &&
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
!ssl->options.verifyPostHandshake &&
#endif
!ssl->options.havePeerCert && !ssl->options.failNoCert) {
ssl->options.peerAuthGood = 1;
}
/* SERVER: check peer authentication. */
if (!ssl->options.peerAuthGood) {
WOLFSSL_MSG("Client authentication did not happen");
return WOLFSSL_FATAL_ERROR;