forked from wolfSSL/wolfssl
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:
@@ -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);
|
||||
|
@@ -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
157
src/ssl.c
@@ -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
|
||||
|
18
src/tls13.c
18
src/tls13.c
@@ -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;
|
||||
|
370
tests/api.c
370
tests/api.c
@@ -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),
|
||||
|
@@ -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);
|
||||
|
@@ -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(
|
||||
|
Reference in New Issue
Block a user