Files
mars-matrixssl/matrixssl/tls13Negotiate.c
Janne Johansson 69b5f2c6c3 MatrixSSL 4.5.1
2022-07-29 12:30:12 +03:00

200 lines
6.0 KiB
C

/**
* @file tls13Negotiate.c
* @version $Format:%h%d$
*
* TLS 1.3 specific functions for parameter negotiation.
*/
/*
* Copyright (c) 2018 Rambus Inc.
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from Rambus at
* http://www.rambus.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#include "matrixsslImpl.h"
#ifdef USE_TLS_1_3
# ifdef USE_IDENTITY_CERTIFICATES
/** This function is called to validate our private key and cert chain
against against the peer's signature_algorithms,
signature_algorithms_cert and supported_groups extensions. */
int32_t tls13TryNegotiateParams(ssl_t *ssl,
const sslCipherSpec_t *spec,
sslIdentity_t *givenKey)
{
psSize_t i;
psBool_t peerCanVerifyCvSig = PS_FALSE;
psBool_t peerCanVerifyChain = PS_TRUE;
psBool_t peerCanVerifyCert;
psX509Cert_t *cert;
/* Check if we have successfully already chosen common PSK in
which case it is used in preference to cert-based
authentication */
if (ssl->sec.tls13ChosenPsk != NULL)
{
return PS_SUCCESS;
}
/* Can the peer verify signatures we generate with our private key?
Note: won't support legacy SHA-1 algorithms in CertificateVerify. */
for (i = 0; i < ssl->sec.keySelect.peerSigAlgsLen; i++)
{
if (tls13IsInsecureSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
continue;
}
# ifdef USE_RSA
if (givenKey->privKey.type == PS_RSA &&
tls13IsRsaSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
peerCanVerifyCvSig = PS_TRUE;
break;
}
# endif
# ifdef USE_ECC
if (givenKey->privKey.type == PS_ECC &&
tls13IsEcdsaSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
peerCanVerifyCvSig = PS_TRUE;
break;
}
# endif
# ifdef USE_ED25519
if (givenKey->privKey.type == PS_ED25519 &&
ssl->sec.keySelect.peerSigAlgs[i] == sigalg_ed25519)
{
peerCanVerifyCvSig = PS_TRUE;
break;
}
# endif
# ifdef USE_SM2
if (givenKey->privKey.type == PS_ECC &&
ssl->sec.keySelect.peerSigAlgs[i] == sigalg_sm2sig_sm3)
{
peerCanVerifyCvSig = PS_TRUE;
break;
}
# endif
}
if (!peerCanVerifyCvSig)
{
psTraceErrr("Failed to negotiate CV sig alg\n");
return PS_UNSUPPORTED_FAIL;
}
/*
Can the peer verify all signatures in our cert chain?
Note: we always support SHA-256 and SHA-384 in TLS 1.3.*/
cert = givenKey->cert;
while (cert)
{
peerCanVerifyCert = PS_FALSE;
for (i = 0; i < ssl->sec.keySelect.peerSigAlgsLen; i++)
{
# ifdef USE_CERT_PARSE
if (!Memcmp(cert->subject.hash,
cert->issuer.hash,
SHA1_HASH_SIZE))
{
/* Root cert. Peer doesn't need to verify. */
peerCanVerifyCert = PS_TRUE;
}
# else
if (0)
{
}
# endif
# ifdef USE_RSA
else if (cert->sigAlgorithm == OID_SHA256_RSA_SIG ||
cert->sigAlgorithm == OID_SHA384_RSA_SIG)
{
if (tls13IsRsaSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
peerCanVerifyCert = PS_TRUE;
}
}
# endif
# ifdef USE_ECC
else if (cert->sigAlgorithm == OID_SHA256_ECDSA_SIG ||
cert->sigAlgorithm == OID_SHA384_ECDSA_SIG)
{
if (tls13IsEcdsaSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
peerCanVerifyCert = PS_TRUE;
}
}
# endif
# ifdef USE_ED25519
else if (cert->sigAlgorithm == OID_ED25519_KEY_ALG &&
ssl->sec.keySelect.peerSigAlgs[i] == sigalg_ed25519)
{
peerCanVerifyCert = PS_TRUE;
}
# endif
# ifdef USE_SM2
else if (cert->sigAlgorithm == OID_SM3_SM2_SIG &&
ssl->sec.keySelect.peerSigAlgs[i] == sigalg_sm2sig_sm3)
{
peerCanVerifyCert = PS_TRUE;
}
# endif
else
{
if (cert->sigAlgorithm == OID_ED25519_KEY_ALG)
{
psTraceErrr("Need USE_ED25519 for Ed25519 sigs in certs\n");
}
else
{
psTraceInfo("TODO: support PSS or SHA-1 sigs in certs.\n");
}
}
}
if (!peerCanVerifyCert)
{
peerCanVerifyChain = PS_FALSE;
break;
}
cert = cert->next;
}
if (peerCanVerifyChain)
{
return PS_SUCCESS;
}
else
{
psTraceErrr("Peer does not support our cert chain sig algs\n");
return PS_UNSUPPORTED_FAIL;
}
}
# endif
#endif /* USE_TLS_1_3 */