Merge pull request #6963 from julek-wolfssl/dynamic-certs-n-ciphers

Add API to choose dynamic certs based on client ciphers/sigalgs
This commit is contained in:
Sean Parkinson
2023-12-08 07:45:36 +10:00
committed by GitHub
7 changed files with 649 additions and 73 deletions

View File

@@ -14854,3 +14854,111 @@ available size need to be provided in bufferSz.
*/ */
int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buffer, int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buffer,
unsigned int bufferSz); unsigned int bufferSz);
/*!
\ingroup TLS
\brief This function returns the raw list of ciphersuites and signature
algorithms offered by the client. The lists are only stored and returned
inside a callback setup with wolfSSL_CTX_set_cert_cb(). This is useful to
be able to dynamically load certificates and keys based on the available
ciphersuites and signature algorithms.
\param [in] ssl The WOLFSSL object to extract the lists from.
\param [out] optional suites Raw and unfiltered list of client ciphersuites
\param [out] optional suiteSz Size of suites in bytes
\param [out] optional hashSigAlgo Raw and unfiltered list of client
signature algorithms
\param [out] optional hashSigAlgoSz Size of hashSigAlgo in bytes
\return WOLFSSL_SUCCESS when suites available
\return WOLFSSL_FAILURE when suites not available
_Example_
\code
int certCB(WOLFSSL* ssl, void* arg)
{
const byte* suites = NULL;
word16 suiteSz = 0;
const byte* hashSigAlgo = NULL;
word16 hashSigAlgoSz = 0;
wolfSSL_get_client_suites_sigalgs(ssl, &suites, &suiteSz, &hashSigAlgo,
&hashSigAlgoSz);
// Choose certificate to load based on ciphersuites and sigalgs
}
WOLFSSL* ctx;
ctx = wolfSSL_CTX_new(wolfTLSv1_3_method_ex(NULL));
wolfSSL_CTX_set_cert_cb(ctx, certCB, NULL);
\endcode
\sa wolfSSL_get_ciphersuite_info
\sa wolfSSL_get_sigalg_info
*/
int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
const byte** suites, word16* suiteSz,
const byte** hashSigAlgo, word16* hashSigAlgoSz);
/*!
\ingroup TLS
\brief This returns information about the ciphersuite directly from the
raw ciphersuite bytes.
\param [in] first First byte of the ciphersuite
\param [in] second Second byte of the ciphersuite
\return WOLFSSL_CIPHERSUITE_INFO A struct containing information about the
type of authentication used in the ciphersuite.
_Example_
\code
WOLFSSL_CIPHERSUITE_INFO info =
wolfSSL_get_ciphersuite_info(suites[0], suites[1]);
if (info.rsaAuth)
haveRSA = 1;
else if (info.eccAuth)
haveECC = 1;
\endcode
\sa wolfSSL_get_client_suites_sigalgs
\sa wolfSSL_get_sigalg_info
*/
WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
byte second);
/*!
\ingroup TLS
\brief This returns information about the hash and signature algorithm
directly from the raw ciphersuite bytes.
\param [in] first First byte of the hash and signature algorithm
\param [in] second Second byte of the hash and signature algorithm
\param [out] hashAlgo The enum wc_HashType of the MAC algorithm
\param [out] sigAlgo The enum Key_Sum of the authentication algorithm
\return 0 when info was correctly set
\return BAD_FUNC_ARG when either input paramters are NULL or the bytes
are not a recognized sigalg suite
_Example_
\code
enum wc_HashType hashAlgo;
enum Key_Sum sigAlgo;
wolfSSL_get_sigalg_info(hashSigAlgo[idx+0], hashSigAlgo[idx+1],
&hashAlgo, &sigAlgo);
if (sigAlgo == RSAk || sigAlgo == RSAPSSk)
haveRSA = 1;
else if (sigAlgo == ECDSAk)
haveECC = 1;
\endcode
\sa wolfSSL_get_client_suites_sigalgs
\sa wolfSSL_get_ciphersuite_info
*/
int wolfSSL_get_sigalg_info(byte first, byte second,
int* hashAlgo, int* sigAlgo);

View File

@@ -4236,7 +4236,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
* hashalgo The hash algorithm. * hashalgo The hash algorithm.
* hsType The signature type. * hsType The signature type.
*/ */
static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
{ {
*hsType = invalid_sa_algo; *hsType = invalid_sa_algo;
switch (input[0]) { switch (input[0]) {
@@ -4324,7 +4324,7 @@ static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsTy
#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ #if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
defined(HAVE_CURVE448) || (!defined(NO_RSA) && defined(WC_RSA_PSS)) defined(HAVE_CURVE448) || (!defined(NO_RSA) && defined(WC_RSA_PSS))
static enum wc_HashType HashAlgoToType(int hashAlgo) enum wc_HashType HashAlgoToType(int hashAlgo)
{ {
switch (hashAlgo) { switch (hashAlgo) {
#ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA512
@@ -11224,23 +11224,11 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
#endif /* WOLFSSL_NO_TLS12 */ #endif /* WOLFSSL_NO_TLS12 */
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
/* cipher requirements */
enum {
REQUIRES_RSA,
REQUIRES_DHE,
REQUIRES_ECC,
REQUIRES_ECC_STATIC,
REQUIRES_PSK,
REQUIRES_RSA_SIG,
REQUIRES_AEAD
};
/* Does this cipher suite (first, second) have the requirement /* Does this cipher suite (first, second) have the requirement
an ephemeral key exchange will still require the key for signing an ephemeral key exchange will still require the key for signing
the key exchange so ECDHE_RSA requires an rsa key thus rsa_kea */ the key exchange so ECDHE_RSA requires an rsa key thus rsa_kea */
static int CipherRequires(byte first, byte second, int requirement) int CipherRequires(byte first, byte second, int requirement)
{ {
(void)requirement; (void)requirement;
@@ -35435,6 +35423,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif #endif
#ifdef OPENSSL_EXTRA #ifdef OPENSSL_EXTRA
ssl->clSuites = clSuites;
/* Give user last chance to provide a cert for cipher selection */ /* Give user last chance to provide a cert for cipher selection */
if (ret == 0 && ssl->ctx->certSetupCb != NULL) if (ret == 0 && ssl->ctx->certSetupCb != NULL)
ret = CertSetupCbWrapper(ssl); ret = CertSetupCbWrapper(ssl);
@@ -35458,7 +35447,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif #endif
out: out:
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
ssl->clSuites = NULL;
#endif
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
if (clSuites != NULL) if (clSuites != NULL)
XFREE(clSuites, ssl->heap, DYNAMIC_TYPE_SUITES); XFREE(clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);

157
src/ssl.c
View File

@@ -16303,6 +16303,163 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ctx->certSetupCbArg = arg; ctx->certSetupCbArg = arg;
} }
int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
const byte** suites, word16* suiteSz,
const byte** hashSigAlgo, word16* hashSigAlgoSz)
{
WOLFSSL_ENTER("wolfSSL_get_client_suites_sigalgs");
if (suites != NULL)
*suites = NULL;
if (suiteSz != NULL)
*suiteSz = 0;
if (hashSigAlgo != NULL)
*hashSigAlgo = NULL;
if (hashSigAlgoSz != NULL)
*hashSigAlgoSz = 0;
if (ssl != NULL && ssl->clSuites != NULL) {
if (suites != NULL && suiteSz != NULL) {
*suites = ssl->clSuites->suites;
*suiteSz = ssl->clSuites->suiteSz;
}
if (hashSigAlgo != NULL && hashSigAlgoSz != NULL) {
*hashSigAlgo = ssl->clSuites->hashSigAlgo;
*hashSigAlgoSz = ssl->clSuites->hashSigAlgoSz;
}
return WOLFSSL_SUCCESS;
}
return WOLFSSL_FAILURE;
}
WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
byte second)
{
WOLFSSL_CIPHERSUITE_INFO info;
info.rsaAuth = (byte)(CipherRequires(first, second, REQUIRES_RSA) ||
CipherRequires(first, second, REQUIRES_RSA_SIG));
info.eccAuth = (byte)(CipherRequires(first, second, REQUIRES_ECC) ||
/* Static ECC ciphers may require RSA for authentication */
(CipherRequires(first, second, REQUIRES_ECC_STATIC) &&
!CipherRequires(first, second, REQUIRES_RSA_SIG)));
info.eccStatic =
(byte)CipherRequires(first, second, REQUIRES_ECC_STATIC);
info.psk = (byte)CipherRequires(first, second, REQUIRES_PSK);
return info;
}
/**
* @param first First byte of the hash and signature algorithm
* @param second Second byte of the hash and signature algorithm
* @param hashAlgo The enum wc_HashType of the MAC algorithm
* @param sigAlgo The enum Key_Sum of the authentication algorithm
*/
int wolfSSL_get_sigalg_info(byte first, byte second,
int* hashAlgo, int* sigAlgo)
{
byte input[2];
byte hashType;
byte sigType;
if (hashAlgo == NULL || sigAlgo == NULL)
return BAD_FUNC_ARG;
input[0] = first;
input[1] = second;
DecodeSigAlg(input, &hashType, &sigType);
/* cast so that compiler reminds us of unimplemented values */
switch ((enum SignatureAlgorithm)sigType) {
case anonymous_sa_algo:
*sigAlgo = (enum Key_Sum)0;
break;
case rsa_sa_algo:
*sigAlgo = RSAk;
break;
case dsa_sa_algo:
*sigAlgo = DSAk;
break;
case ecc_dsa_sa_algo:
*sigAlgo = ECDSAk;
break;
case rsa_pss_sa_algo:
*sigAlgo = RSAPSSk;
break;
case ed25519_sa_algo:
*sigAlgo = ED25519k;
break;
case rsa_pss_pss_algo:
*sigAlgo = RSAPSSk;
break;
case ed448_sa_algo:
*sigAlgo = ED448k;
break;
case falcon_level1_sa_algo:
*sigAlgo = FALCON_LEVEL1k;
break;
case falcon_level5_sa_algo:
*sigAlgo = FALCON_LEVEL5k;
break;
case dilithium_level2_sa_algo:
*sigAlgo = DILITHIUM_LEVEL2k;
break;
case dilithium_level3_sa_algo:
*sigAlgo = DILITHIUM_LEVEL3k;
break;
case dilithium_level5_sa_algo:
*sigAlgo = DILITHIUM_LEVEL5k;
break;
case sm2_sa_algo:
*sigAlgo = SM2k;
break;
case invalid_sa_algo:
default:
*hashAlgo = WC_HASH_TYPE_NONE;
*sigAlgo = 0;
return BAD_FUNC_ARG;
}
/* cast so that compiler reminds us of unimplemented values */
switch((enum wc_MACAlgorithm)hashType) {
case no_mac:
case rmd_mac: /* Don't have a RIPEMD type in wc_HashType */
*hashAlgo = WC_HASH_TYPE_NONE;
break;
case md5_mac:
*hashAlgo = WC_HASH_TYPE_MD5;
break;
case sha_mac:
*hashAlgo = WC_HASH_TYPE_SHA;
break;
case sha224_mac:
*hashAlgo = WC_HASH_TYPE_SHA224;
break;
case sha256_mac:
*hashAlgo = WC_HASH_TYPE_SHA256;
break;
case sha384_mac:
*hashAlgo = WC_HASH_TYPE_SHA384;
break;
case sha512_mac:
*hashAlgo = WC_HASH_TYPE_SHA512;
break;
case blake2b_mac:
*hashAlgo = WC_HASH_TYPE_BLAKE2B;
break;
case sm3_mac:
#ifdef WOLFSSL_SM3
*hashAlgo = WC_HASH_TYPE_SM3;
#else
*hashAlgo = WC_HASH_TYPE_NONE;
#endif
break;
default:
*hashAlgo = WC_HASH_TYPE_NONE;
*sigAlgo = 0;
return BAD_FUNC_ARG;
}
return 0;
}
/** /**
* Internal wrapper for calling certSetupCb * Internal wrapper for calling certSetupCb
* @param ssl The SSL/TLS Object * @param ssl The SSL/TLS Object

View File

@@ -5617,6 +5617,11 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo);
#endif #endif
#ifdef OPENSSL_EXTRA
if ((ret = CertSetupCbWrapper(ssl)) != 0)
return ret;
#endif
if (OPAQUE8_LEN > size) if (OPAQUE8_LEN > size)
return BUFFER_ERROR; return BUFFER_ERROR;
@@ -6594,6 +6599,9 @@ static void FreeDch13Args(WOLFSSL* ssl, void* pArgs)
XFREE(args->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES); XFREE(args->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);
args->clSuites = NULL; args->clSuites = NULL;
} }
#ifdef OPENSSL_EXTRA
ssl->clSuites = NULL;
#endif
} }
int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
@@ -6978,6 +6986,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
case TLS_ASYNC_DO: case TLS_ASYNC_DO:
{ {
#ifdef OPENSSL_EXTRA
ssl->clSuites = args->clSuites;
if ((ret = CertSetupCbWrapper(ssl)) != 0)
goto exit_dch;
#endif
#ifndef NO_CERTS #ifndef NO_CERTS
if (!args->usingPSK) { if (!args->usingPSK) {
if ((ret = MatchSuite(ssl, args->clSuites)) < 0) { if ((ret = MatchSuite(ssl, args->clSuites)) < 0) {
@@ -8244,11 +8257,6 @@ static int SendTls13Certificate(WOLFSSL* ssl)
listSz = 0; listSz = 0;
} }
else { else {
#ifdef OPENSSL_EXTRA
if ((ret = CertSetupCbWrapper(ssl)) != 0)
return ret;
#endif
if (!ssl->buffers.certificate) { if (!ssl->buffers.certificate) {
WOLFSSL_MSG("Send Cert missing certificate buffer"); WOLFSSL_MSG("Send Cert missing certificate buffer");
return BUFFER_ERROR; return BUFFER_ERROR;

View File

@@ -370,7 +370,7 @@
defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) || \ defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) || \
defined(WOLFSSL_TEST_STATIC_BUILD) || defined(WOLFSSL_DTLS) || \ defined(WOLFSSL_TEST_STATIC_BUILD) || defined(WOLFSSL_DTLS) || \
defined(HAVE_ECH) || defined(HAVE_EX_DATA) || !defined(NO_SESSION_CACHE) \ defined(HAVE_ECH) || defined(HAVE_EX_DATA) || !defined(NO_SESSION_CACHE) \
|| !defined(WOLFSSL_NO_TLS12) || !defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)
/* for testing SSL_get_peer_cert_chain, or SESSION_TICKET_HINT_DEFAULT, /* for testing SSL_get_peer_cert_chain, or SESSION_TICKET_HINT_DEFAULT,
* for setting authKeyIdSrc in WOLFSSL_X509, or testing DTLS sequence * for setting authKeyIdSrc in WOLFSSL_X509, or testing DTLS sequence
* number tracking */ * number tracking */
@@ -5824,8 +5824,12 @@ static WC_INLINE int test_ssl_memio_setup(test_ssl_memio_ctx *ctx)
#ifdef WOLFSSL_ENCRYPTED_KEYS #ifdef WOLFSSL_ENCRYPTED_KEYS
wolfSSL_CTX_set_default_passwd_cb(ctx->c_ctx, PasswordCallBack); wolfSSL_CTX_set_default_passwd_cb(ctx->c_ctx, PasswordCallBack);
#endif #endif
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->c_ctx, caCertFile, 0), if (ctx->c_cb.caPemFile != NULL)
WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->c_ctx,
ctx->c_cb.caPemFile, 0), WOLFSSL_SUCCESS);
else
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->c_ctx,
caCertFile, 0), WOLFSSL_SUCCESS);
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
if (!c_sharedCtx) if (!c_sharedCtx)
#endif #endif
@@ -5889,8 +5893,12 @@ static WC_INLINE int test_ssl_memio_setup(test_ssl_memio_ctx *ctx)
wolfSSL_SetIOSend(ctx->s_ctx, test_ssl_memio_write_cb); wolfSSL_SetIOSend(ctx->s_ctx, test_ssl_memio_write_cb);
wolfSSL_CTX_set_verify(ctx->s_ctx, WOLFSSL_VERIFY_PEER | wolfSSL_CTX_set_verify(ctx->s_ctx, WOLFSSL_VERIFY_PEER |
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->s_ctx, cliCertFile, 0), if (ctx->s_cb.caPemFile != NULL)
WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->s_ctx,
ctx->s_cb.caPemFile, 0), WOLFSSL_SUCCESS);
else
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->s_ctx,
cliCertFile, 0), WOLFSSL_SUCCESS);
#ifdef WOLFSSL_ENCRYPTED_KEYS #ifdef WOLFSSL_ENCRYPTED_KEYS
wolfSSL_CTX_set_default_passwd_cb(ctx->s_ctx, PasswordCallBack); wolfSSL_CTX_set_default_passwd_cb(ctx->s_ctx, PasswordCallBack);
#endif #endif
@@ -44748,60 +44756,40 @@ static int test_wolfSSL_BIO_reset(void)
/* test that the callback arg is correct */ /* test that the callback arg is correct */
static int certCbArg = 0; static int certCbArg = 0;
static int clientCertCb(WOLFSSL* ssl, void* arg) static int certCb(WOLFSSL* ssl, void* arg)
{ {
if (ssl == NULL || arg != &certCbArg) if (ssl == NULL || arg != &certCbArg)
return 0; return 0;
if (wolfSSL_use_certificate_file(ssl, cliCertFile, if (wolfSSL_is_server(ssl)) {
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) if (wolfSSL_use_certificate_file(ssl, svrCertFile,
return 0; WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
if (wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, return 0;
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) if (wolfSSL_use_PrivateKey_file(ssl, svrKeyFile,
return 0; WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
return 0;
}
else {
if (wolfSSL_use_certificate_file(ssl, cliCertFile,
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
return 0;
if (wolfSSL_use_PrivateKey_file(ssl, cliKeyFile,
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
return 0;
}
return 1; return 1;
} }
static int clientCertSetupCb(WOLFSSL_CTX* ctx) static int certSetupCb(WOLFSSL_CTX* ctx)
{ {
SSL_CTX_set_cert_cb(ctx, clientCertCb, &certCbArg); SSL_CTX_set_cert_cb(ctx, certCb, &certCbArg);
return TEST_SUCCESS; return TEST_SUCCESS;
} }
/** /**
* This is only done because test_client_nofail has no way to stop * This is only done because test_wolfSSL_client_server_nofail_memio has no way
* certificate and key loading * to stop certificate and key loading
*/ */
static int clientCertClearCb(WOLFSSL* ssl) static int certClearCb(WOLFSSL* ssl)
{
/* Clear the loaded certs to force the callbacks to set them up */
SSL_certs_clear(ssl);
return TEST_SUCCESS;
}
static int serverCertCb(WOLFSSL* ssl, void* arg)
{
if (ssl == NULL || arg != &certCbArg)
return 0;
if (wolfSSL_use_certificate_file(ssl, svrCertFile,
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
return 0;
if (wolfSSL_use_PrivateKey_file(ssl, svrKeyFile,
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
return 0;
return 1;
}
static int serverCertSetupCb(WOLFSSL_CTX* ctx)
{
SSL_CTX_set_cert_cb(ctx, serverCertCb, &certCbArg);
return TEST_SUCCESS;
}
/**
* This is only done because test_server_nofail has no way to stop
* certificate and key loading
*/
static int serverCertClearCb(WOLFSSL* ssl)
{ {
/* Clear the loaded certs to force the callbacks to set them up */ /* Clear the loaded certs to force the callbacks to set them up */
SSL_certs_clear(ssl); SSL_certs_clear(ssl);
@@ -44820,10 +44808,10 @@ static int test_wolfSSL_cert_cb(void)
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
func_cb_client.ctx_ready = clientCertSetupCb; func_cb_client.ctx_ready = certSetupCb;
func_cb_client.ssl_ready = clientCertClearCb; func_cb_client.ssl_ready = certClearCb;
func_cb_server.ctx_ready = serverCertSetupCb; func_cb_server.ctx_ready = certSetupCb;
func_cb_server.ssl_ready = serverCertClearCb; func_cb_server.ssl_ready = certClearCb;
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
&func_cb_server, NULL), TEST_SUCCESS); &func_cb_server, NULL), TEST_SUCCESS);
@@ -44831,6 +44819,295 @@ static int test_wolfSSL_cert_cb(void)
return EXPECT_RESULT(); return EXPECT_RESULT();
} }
#if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES)
static const char* test_wolfSSL_cert_cb_dyn_ciphers_client_cipher = NULL;
static const char* test_wolfSSL_cert_cb_dyn_ciphers_client_sigalgs = NULL;
static int test_wolfSSL_cert_cb_dyn_ciphers_client_ctx_ready(WOLFSSL_CTX* ctx)
{
EXPECT_DECLS;
ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx,
test_wolfSSL_cert_cb_dyn_ciphers_client_cipher), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx,
test_wolfSSL_cert_cb_dyn_ciphers_client_sigalgs), WOLFSSL_SUCCESS);
return EXPECT_RESULT();
}
static int test_wolfSSL_cert_cb_dyn_ciphers_certCB(WOLFSSL* ssl, void* arg)
{
const byte* suites = NULL;
word16 suiteSz = 0;
const byte* hashSigAlgo = NULL;
word16 hashSigAlgoSz = 0;
word16 idx = 0;
int haveRSA = 0;
int haveECC = 0;
(void)arg;
if (wolfSSL_get_client_suites_sigalgs(ssl, &suites, &suiteSz, &hashSigAlgo,
&hashSigAlgoSz) != WOLFSSL_SUCCESS)
return 0;
if (suites == NULL || suiteSz == 0 || hashSigAlgo == NULL ||
hashSigAlgoSz == 0)
return 0;
for (idx = 0; idx < suiteSz; idx += 2) {
WOLFSSL_CIPHERSUITE_INFO info =
wolfSSL_get_ciphersuite_info(suites[idx], suites[idx+1]);
if (info.rsaAuth)
haveRSA = 1;
else if (info.eccAuth)
haveECC = 1;
}
if (hashSigAlgoSz > 0) {
/* sigalgs extension takes precedence over ciphersuites */
haveRSA = 0;
haveECC = 0;
}
for (idx = 0; idx < hashSigAlgoSz; idx += 2) {
int hashAlgo;
int sigAlgo;
if (wolfSSL_get_sigalg_info(hashSigAlgo[idx+0], hashSigAlgo[idx+1],
&hashAlgo, &sigAlgo) != 0)
return 0;
if (sigAlgo == RSAk || sigAlgo == RSAPSSk)
haveRSA = 1;
else if (sigAlgo == ECDSAk)
haveECC = 1;
}
if (haveRSA) {
if (wolfSSL_use_certificate_file(ssl, svrCertFile, WOLFSSL_FILETYPE_PEM)
!= WOLFSSL_SUCCESS)
return 0;
if (wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, WOLFSSL_FILETYPE_PEM)
!= WOLFSSL_SUCCESS)
return 0;
}
else if (haveECC) {
if (wolfSSL_use_certificate_file(ssl, eccCertFile, WOLFSSL_FILETYPE_PEM)
!= WOLFSSL_SUCCESS)
return 0;
if (wolfSSL_use_PrivateKey_file(ssl, eccKeyFile, WOLFSSL_FILETYPE_PEM)
!= WOLFSSL_SUCCESS)
return 0;
}
return 1;
}
static int test_wolfSSL_cert_cb_dyn_ciphers_server_ctx_ready(WOLFSSL_CTX* ctx)
{
SSL_CTX_set_cert_cb(ctx, test_wolfSSL_cert_cb_dyn_ciphers_certCB, NULL);
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
return TEST_SUCCESS;
}
#endif
/* Testing dynamic ciphers offered by client */
static int test_wolfSSL_cert_cb_dyn_ciphers(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES)
test_ssl_cbf func_cb_client;
test_ssl_cbf func_cb_server;
struct {
method_provider client_meth;
const char* client_ciphers;
const char* client_sigalgs;
const char* client_ca;
method_provider server_meth;
} test_params[] = {
#if !defined(NO_SHA256) && defined(HAVE_AESGCM)
#ifdef WOLFSSL_TLS13
#if !defined(NO_RSA) && defined(WC_RSA_PSS)
{wolfTLSv1_3_client_method,
"TLS13-AES256-GCM-SHA384:TLS13-AES128-GCM-SHA256",
"RSA-PSS+SHA256", caCertFile, wolfTLSv1_3_server_method},
#endif
#ifdef HAVE_ECC
{wolfTLSv1_3_client_method,
"TLS13-AES256-GCM-SHA384:TLS13-AES128-GCM-SHA256",
"ECDSA+SHA256", caEccCertFile, wolfTLSv1_3_server_method},
#endif
#endif
#ifndef WOLFSSL_NO_TLS12
#if !defined(NO_RSA) && defined(WC_RSA_PSS) && !defined(NO_DH)
{wolfTLSv1_2_client_method,
"DHE-RSA-AES128-GCM-SHA256",
"RSA-PSS+SHA256", caCertFile, wolfTLSv1_2_server_method},
#endif
#ifdef HAVE_ECC
{wolfTLSv1_2_client_method,
"ECDHE-ECDSA-AES128-GCM-SHA256",
"ECDSA+SHA256", caEccCertFile, wolfTLSv1_2_server_method},
#endif
#endif
#endif
};
size_t i;
for (i = 0; i < sizeof(test_params)/sizeof(*test_params); i++) {
printf("\tTesting %s ciphers with %s sigalgs\n",
test_params[i].client_ciphers, test_params[i].client_sigalgs);
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
test_wolfSSL_cert_cb_dyn_ciphers_client_cipher =
test_params[i].client_ciphers;
test_wolfSSL_cert_cb_dyn_ciphers_client_sigalgs =
test_params[i].client_sigalgs;
func_cb_client.method = test_params[i].client_meth;
func_cb_client.caPemFile = test_params[i].client_ca;
func_cb_client.ctx_ready =
test_wolfSSL_cert_cb_dyn_ciphers_client_ctx_ready;
func_cb_server.ctx_ready =
test_wolfSSL_cert_cb_dyn_ciphers_server_ctx_ready;
func_cb_server.ssl_ready = certClearCb; /* Reuse from previous test */
func_cb_server.method = test_params[i].server_meth;
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
&func_cb_server, NULL), TEST_SUCCESS);
}
#endif
return EXPECT_RESULT();
}
static int test_wolfSSL_ciphersuite_auth(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
WOLFSSL_CIPHERSUITE_INFO info;
(void)info;
#ifndef WOLFSSL_NO_TLS12
#ifdef HAVE_CHACHA
info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
ExpectIntEQ(info.rsaAuth, 1);
ExpectIntEQ(info.eccAuth, 0);
ExpectIntEQ(info.eccStatic, 0);
ExpectIntEQ(info.psk, 0);
info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
ExpectIntEQ(info.rsaAuth, 0);
ExpectIntEQ(info.eccAuth, 1);
ExpectIntEQ(info.eccStatic, 0);
ExpectIntEQ(info.psk, 0);
info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE,
TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256);
ExpectIntEQ(info.rsaAuth, 0);
ExpectIntEQ(info.eccAuth, 0);
ExpectIntEQ(info.eccStatic, 0);
ExpectIntEQ(info.psk, 1);
#endif
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
#ifndef NO_RSA
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
ExpectIntEQ(info.rsaAuth, 1);
ExpectIntEQ(info.eccAuth, 0);
ExpectIntEQ(info.eccStatic, 0);
ExpectIntEQ(info.psk, 0);
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA);
ExpectIntEQ(info.rsaAuth, 1);
ExpectIntEQ(info.eccAuth, 0);
ExpectIntEQ(info.eccStatic, 1);
ExpectIntEQ(info.psk, 0);
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA);
ExpectIntEQ(info.rsaAuth, 1);
ExpectIntEQ(info.eccAuth, 0);
ExpectIntEQ(info.eccStatic, 1);
ExpectIntEQ(info.psk, 0);
#endif
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
ExpectIntEQ(info.rsaAuth, 0);
ExpectIntEQ(info.eccAuth, 1);
ExpectIntEQ(info.eccStatic, 0);
ExpectIntEQ(info.psk, 0);
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA);
ExpectIntEQ(info.rsaAuth, 0);
ExpectIntEQ(info.eccAuth, 1);
ExpectIntEQ(info.eccStatic, 1);
ExpectIntEQ(info.psk, 0);
info = wolfSSL_get_ciphersuite_info(ECDHE_PSK_BYTE,
TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256);
ExpectIntEQ(info.rsaAuth, 0);
ExpectIntEQ(info.eccAuth, 0);
ExpectIntEQ(info.eccStatic, 0);
ExpectIntEQ(info.psk, 1);
#endif
#endif
#ifdef WOLFSSL_TLS13
info = wolfSSL_get_ciphersuite_info(TLS13_BYTE,
TLS_AES_128_GCM_SHA256);
ExpectIntEQ(info.rsaAuth, 0);
ExpectIntEQ(info.eccAuth, 0);
ExpectIntEQ(info.eccStatic, 0);
ExpectIntEQ(info.psk, 0);
#endif
#endif
return EXPECT_RESULT();
}
static int test_wolfSSL_sigalg_info(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
byte hashSigAlgo[WOLFSSL_MAX_SIGALGO];
word16 len = 0;
word16 idx = 0;
int allSigAlgs = SIG_ECDSA | SIG_RSA | SIG_SM2 | SIG_FALCON | SIG_DILITHIUM;
InitSuitesHashSigAlgo_ex2(hashSigAlgo, allSigAlgs, 1, 0xFFFFFFFF, &len);
for (idx = 0; idx < len; idx += 2) {
int hashAlgo;
int sigAlgo;
ExpectIntEQ(wolfSSL_get_sigalg_info(hashSigAlgo[idx+0],
hashSigAlgo[idx+1], &hashAlgo, &sigAlgo), 0);
ExpectIntNE(hashAlgo, 0);
ExpectIntNE(sigAlgo, 0);
}
InitSuitesHashSigAlgo_ex2(hashSigAlgo, allSigAlgs | SIG_ANON, 1,
0xFFFFFFFF, &len);
for (idx = 0; idx < len; idx += 2) {
int hashAlgo;
int sigAlgo;
ExpectIntEQ(wolfSSL_get_sigalg_info(hashSigAlgo[idx+0],
hashSigAlgo[idx+1], &hashAlgo, &sigAlgo), 0);
ExpectIntNE(hashAlgo, 0);
}
#endif
return EXPECT_RESULT();
}
static int test_wolfSSL_SESSION(void) static int test_wolfSSL_SESSION(void)
{ {
EXPECT_DECLS; EXPECT_DECLS;
@@ -69051,6 +69328,9 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_check_domain), TEST_DECL(test_wolfSSL_check_domain),
#endif #endif
TEST_DECL(test_wolfSSL_cert_cb), TEST_DECL(test_wolfSSL_cert_cb),
TEST_DECL(test_wolfSSL_cert_cb_dyn_ciphers),
TEST_DECL(test_wolfSSL_ciphersuite_auth),
TEST_DECL(test_wolfSSL_sigalg_info),
/* Can't memory test as tcp_connect aborts. */ /* Can't memory test as tcp_connect aborts. */
TEST_DECL(test_wolfSSL_SESSION), TEST_DECL(test_wolfSSL_SESSION),
TEST_DECL(test_wolfSSL_SESSION_expire_downgrade), TEST_DECL(test_wolfSSL_SESSION_expire_downgrade),

View File

@@ -2352,7 +2352,8 @@ WOLFSSL_LOCAL void InitSuitesHashSigAlgo_ex(byte* hashSigAlgo, int haveECDSAsig,
int haveRSAsig, int haveFalconSig, int haveRSAsig, int haveFalconSig,
int haveDilithiumSig, int haveAnon, int haveDilithiumSig, int haveAnon,
int tls1_2, int keySz, word16* len); int tls1_2, int keySz, word16* len);
WOLFSSL_LOCAL void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int have, /* use wolfSSL_API visibility to be able to test in tests/api.c */
WOLFSSL_API void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int have,
int tls1_2, int keySz, int tls1_2, int keySz,
word16* len); word16* len);
WOLFSSL_LOCAL int AllocateCtxSuites(WOLFSSL_CTX* ctx); WOLFSSL_LOCAL int AllocateCtxSuites(WOLFSSL_CTX* ctx);
@@ -5389,6 +5390,9 @@ struct WOLFSSL {
* re-using the context's object. When WOLFSSL * re-using the context's object. When WOLFSSL
* object needs separate instance of suites use * object needs separate instance of suites use
* AllocateSuites(). */ * AllocateSuites(). */
#ifdef OPENSSL_EXTRA
const Suites* clSuites;
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
WOLF_STACK_OF(WOLFSSL_CIPHER)* suitesStack; /* stack of available cipher WOLF_STACK_OF(WOLFSSL_CIPHER)* suitesStack; /* stack of available cipher
* suites */ * suites */
@@ -6011,6 +6015,16 @@ enum ProvisionSide {
PROVISION_CLIENT_SERVER = 3 PROVISION_CLIENT_SERVER = 3
}; };
/* cipher requirements */
enum {
REQUIRES_RSA,
REQUIRES_DHE,
REQUIRES_ECC,
REQUIRES_ECC_STATIC,
REQUIRES_PSK,
REQUIRES_RSA_SIG,
REQUIRES_AEAD
};
static const byte kTlsClientStr[SIZEOF_SENDER+1] = { 0x43, 0x4C, 0x4E, 0x54, 0x00 }; /* CLNT */ static const byte kTlsClientStr[SIZEOF_SENDER+1] = { 0x43, 0x4C, 0x4E, 0x54, 0x00 }; /* CLNT */
static const byte kTlsServerStr[SIZEOF_SENDER+1] = { 0x53, 0x52, 0x56, 0x52, 0x00 }; /* SRVR */ static const byte kTlsServerStr[SIZEOF_SENDER+1] = { 0x53, 0x52, 0x56, 0x52, 0x00 }; /* SRVR */
@@ -6102,6 +6116,7 @@ WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree);
WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl);
WOLFSSL_LOCAL byte* GetOutputBuffer(WOLFSSL* ssl); WOLFSSL_LOCAL byte* GetOutputBuffer(WOLFSSL* ssl);
WOLFSSL_LOCAL int CipherRequires(byte first, byte second, int requirement);
WOLFSSL_LOCAL int VerifyClientSuite(word16 havePSK, byte cipherSuite0, WOLFSSL_LOCAL int VerifyClientSuite(word16 havePSK, byte cipherSuite0,
byte cipherSuite); byte cipherSuite);
@@ -6311,6 +6326,10 @@ WOLFSSL_LOCAL word32 LowResTimer(void);
WOLFSSL_LOCAL int FindSuiteSSL(const WOLFSSL* ssl, byte* suite); WOLFSSL_LOCAL int FindSuiteSSL(const WOLFSSL* ssl, byte* suite);
WOLFSSL_LOCAL void DecodeSigAlg(const byte* input, byte* hashAlgo,
byte* hsType);
WOLFSSL_LOCAL enum wc_HashType HashAlgoToType(int hashAlgo);
#ifndef NO_CERTS #ifndef NO_CERTS
WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag, WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag,
void* heap); void* heap);

View File

@@ -2121,6 +2121,19 @@ WOLFSSL_API void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb
typedef int (*CertSetupCallback)(WOLFSSL* ssl, void*); typedef int (*CertSetupCallback)(WOLFSSL* ssl, void*);
WOLFSSL_API void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, WOLFSSL_API void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx,
CertSetupCallback cb, void *arg); CertSetupCallback cb, void *arg);
WOLFSSL_API int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
const byte** suites, word16* suiteSz,
const byte** hashSigAlgo, word16* hashSigAlgoSz);
typedef struct WOLFSSL_CIPHERSUITE_INFO {
byte rsaAuth:1;
byte eccAuth:1;
byte eccStatic:1;
byte psk:1;
} WOLFSSL_CIPHERSUITE_INFO;
WOLFSSL_API WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
byte second);
WOLFSSL_API int wolfSSL_get_sigalg_info(byte first,
byte second, int* hashAlgo, int* sigAlgo);
WOLFSSL_LOCAL int CertSetupCbWrapper(WOLFSSL* ssl); WOLFSSL_LOCAL int CertSetupCbWrapper(WOLFSSL* ssl);
WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data( WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(