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,
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.
* 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;
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) || \
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) {
#ifdef WOLFSSL_SHA512
@@ -11224,23 +11224,11 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
#endif /* WOLFSSL_NO_TLS12 */
#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
an ephemeral key exchange will still require the key for signing
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;
@@ -35435,6 +35423,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
#ifdef OPENSSL_EXTRA
ssl->clSuites = clSuites;
/* Give user last chance to provide a cert for cipher selection */
if (ret == 0 && ssl->ctx->certSetupCb != NULL)
ret = CertSetupCbWrapper(ssl);
@@ -35458,7 +35447,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
out:
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
ssl->clSuites = NULL;
#endif
#ifdef WOLFSSL_SMALL_STACK
if (clSuites != NULL)
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;
}
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
* @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);
#endif
#ifdef OPENSSL_EXTRA
if ((ret = CertSetupCbWrapper(ssl)) != 0)
return ret;
#endif
if (OPAQUE8_LEN > size)
return BUFFER_ERROR;
@@ -6594,6 +6599,9 @@ static void FreeDch13Args(WOLFSSL* ssl, void* pArgs)
XFREE(args->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);
args->clSuites = NULL;
}
#ifdef OPENSSL_EXTRA
ssl->clSuites = NULL;
#endif
}
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:
{
#ifdef OPENSSL_EXTRA
ssl->clSuites = args->clSuites;
if ((ret = CertSetupCbWrapper(ssl)) != 0)
goto exit_dch;
#endif
#ifndef NO_CERTS
if (!args->usingPSK) {
if ((ret = MatchSuite(ssl, args->clSuites)) < 0) {
@@ -8244,11 +8257,6 @@ static int SendTls13Certificate(WOLFSSL* ssl)
listSz = 0;
}
else {
#ifdef OPENSSL_EXTRA
if ((ret = CertSetupCbWrapper(ssl)) != 0)
return ret;
#endif
if (!ssl->buffers.certificate) {
WOLFSSL_MSG("Send Cert missing certificate buffer");
return BUFFER_ERROR;

View File

@@ -370,7 +370,7 @@
defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) || \
defined(WOLFSSL_TEST_STATIC_BUILD) || defined(WOLFSSL_DTLS) || \
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 setting authKeyIdSrc in WOLFSSL_X509, or testing DTLS sequence
* number tracking */
@@ -5824,8 +5824,12 @@ static WC_INLINE int test_ssl_memio_setup(test_ssl_memio_ctx *ctx)
#ifdef WOLFSSL_ENCRYPTED_KEYS
wolfSSL_CTX_set_default_passwd_cb(ctx->c_ctx, PasswordCallBack);
#endif
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->c_ctx, caCertFile, 0),
WOLFSSL_SUCCESS);
if (ctx->c_cb.caPemFile != NULL)
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 (!c_sharedCtx)
#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_CTX_set_verify(ctx->s_ctx, WOLFSSL_VERIFY_PEER |
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->s_ctx, cliCertFile, 0),
WOLFSSL_SUCCESS);
if (ctx->s_cb.caPemFile != NULL)
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
wolfSSL_CTX_set_default_passwd_cb(ctx->s_ctx, PasswordCallBack);
#endif
@@ -44748,60 +44756,40 @@ static int test_wolfSSL_BIO_reset(void)
/* test that the callback arg is correct */
static int certCbArg = 0;
static int clientCertCb(WOLFSSL* ssl, void* arg)
{
if (ssl == NULL || arg != &certCbArg)
return 0;
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;
}
static int clientCertSetupCb(WOLFSSL_CTX* ctx)
{
SSL_CTX_set_cert_cb(ctx, clientCertCb, &certCbArg);
return TEST_SUCCESS;
}
/**
* This is only done because test_client_nofail has no way to stop
* certificate and key loading
*/
static int clientCertClearCb(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)
static int certCb(WOLFSSL* ssl, void* arg)
{
if (ssl == NULL || arg != &certCbArg)
return 0;
if (wolfSSL_is_server(ssl)) {
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 (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;
}
static int serverCertSetupCb(WOLFSSL_CTX* ctx)
static int certSetupCb(WOLFSSL_CTX* ctx)
{
SSL_CTX_set_cert_cb(ctx, serverCertCb, &certCbArg);
SSL_CTX_set_cert_cb(ctx, certCb, &certCbArg);
return TEST_SUCCESS;
}
/**
* This is only done because test_server_nofail has no way to stop
* certificate and key loading
* This is only done because test_wolfSSL_client_server_nofail_memio has no way
* to stop certificate and key loading
*/
static int serverCertClearCb(WOLFSSL* ssl)
static int certClearCb(WOLFSSL* ssl)
{
/* Clear the loaded certs to force the callbacks to set them up */
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_server, 0, sizeof(func_cb_server));
func_cb_client.ctx_ready = clientCertSetupCb;
func_cb_client.ssl_ready = clientCertClearCb;
func_cb_server.ctx_ready = serverCertSetupCb;
func_cb_server.ssl_ready = serverCertClearCb;
func_cb_client.ctx_ready = certSetupCb;
func_cb_client.ssl_ready = certClearCb;
func_cb_server.ctx_ready = certSetupCb;
func_cb_server.ssl_ready = certClearCb;
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
&func_cb_server, NULL), TEST_SUCCESS);
@@ -44831,6 +44819,295 @@ static int test_wolfSSL_cert_cb(void)
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)
{
EXPECT_DECLS;
@@ -69051,6 +69328,9 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_check_domain),
#endif
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. */
TEST_DECL(test_wolfSSL_SESSION),
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 haveDilithiumSig, int haveAnon,
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,
word16* len);
WOLFSSL_LOCAL int AllocateCtxSuites(WOLFSSL_CTX* ctx);
@@ -5389,6 +5390,9 @@ struct WOLFSSL {
* re-using the context's object. When WOLFSSL
* object needs separate instance of suites use
* AllocateSuites(). */
#ifdef OPENSSL_EXTRA
const Suites* clSuites;
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
WOLF_STACK_OF(WOLFSSL_CIPHER)* suitesStack; /* stack of available cipher
* suites */
@@ -6011,6 +6015,16 @@ enum ProvisionSide {
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 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 byte* GetOutputBuffer(WOLFSSL* ssl);
WOLFSSL_LOCAL int CipherRequires(byte first, byte second, int requirement);
WOLFSSL_LOCAL int VerifyClientSuite(word16 havePSK, byte cipherSuite0,
byte cipherSuite);
@@ -6311,6 +6326,10 @@ WOLFSSL_LOCAL word32 LowResTimer(void);
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
WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag,
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*);
WOLFSSL_API void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx,
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_API void* wolfSSL_X509_STORE_CTX_get_ex_data(