Skip to content

Commit 6c8bf7b

Browse files
authored
Merge pull request #6963 from julek-wolfssl/dynamic-certs-n-ciphers
Add API to choose dynamic certs based on client ciphers/sigalgs
2 parents 61b0efc + fbe79d7 commit 6c8bf7b

7 files changed

Lines changed: 644 additions & 68 deletions

File tree

doc/dox_comments/header_files/ssl.h

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14854,3 +14854,111 @@ available size need to be provided in bufferSz.
1485414854
*/
1485514855
int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buffer,
1485614856
unsigned int bufferSz);
14857+
14858+
/*!
14859+
\ingroup TLS
14860+
14861+
\brief This function returns the raw list of ciphersuites and signature
14862+
algorithms offered by the client. The lists are only stored and returned
14863+
inside a callback setup with wolfSSL_CTX_set_cert_cb(). This is useful to
14864+
be able to dynamically load certificates and keys based on the available
14865+
ciphersuites and signature algorithms.
14866+
14867+
\param [in] ssl The WOLFSSL object to extract the lists from.
14868+
\param [out] optional suites Raw and unfiltered list of client ciphersuites
14869+
\param [out] optional suiteSz Size of suites in bytes
14870+
\param [out] optional hashSigAlgo Raw and unfiltered list of client
14871+
signature algorithms
14872+
\param [out] optional hashSigAlgoSz Size of hashSigAlgo in bytes
14873+
\return WOLFSSL_SUCCESS when suites available
14874+
\return WOLFSSL_FAILURE when suites not available
14875+
14876+
_Example_
14877+
\code
14878+
int certCB(WOLFSSL* ssl, void* arg)
14879+
{
14880+
const byte* suites = NULL;
14881+
word16 suiteSz = 0;
14882+
const byte* hashSigAlgo = NULL;
14883+
word16 hashSigAlgoSz = 0;
14884+
14885+
wolfSSL_get_client_suites_sigalgs(ssl, &suites, &suiteSz, &hashSigAlgo,
14886+
&hashSigAlgoSz);
14887+
14888+
// Choose certificate to load based on ciphersuites and sigalgs
14889+
}
14890+
14891+
WOLFSSL* ctx;
14892+
ctx = wolfSSL_CTX_new(wolfTLSv1_3_method_ex(NULL));
14893+
wolfSSL_CTX_set_cert_cb(ctx, certCB, NULL);
14894+
\endcode
14895+
14896+
\sa wolfSSL_get_ciphersuite_info
14897+
\sa wolfSSL_get_sigalg_info
14898+
*/
14899+
int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
14900+
const byte** suites, word16* suiteSz,
14901+
const byte** hashSigAlgo, word16* hashSigAlgoSz);
14902+
14903+
/*!
14904+
\ingroup TLS
14905+
14906+
\brief This returns information about the ciphersuite directly from the
14907+
raw ciphersuite bytes.
14908+
14909+
\param [in] first First byte of the ciphersuite
14910+
\param [in] second Second byte of the ciphersuite
14911+
14912+
\return WOLFSSL_CIPHERSUITE_INFO A struct containing information about the
14913+
type of authentication used in the ciphersuite.
14914+
14915+
_Example_
14916+
\code
14917+
WOLFSSL_CIPHERSUITE_INFO info =
14918+
wolfSSL_get_ciphersuite_info(suites[0], suites[1]);
14919+
if (info.rsaAuth)
14920+
haveRSA = 1;
14921+
else if (info.eccAuth)
14922+
haveECC = 1;
14923+
\endcode
14924+
14925+
\sa wolfSSL_get_client_suites_sigalgs
14926+
\sa wolfSSL_get_sigalg_info
14927+
*/
14928+
WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
14929+
byte second);
14930+
14931+
/*!
14932+
\ingroup TLS
14933+
14934+
\brief This returns information about the hash and signature algorithm
14935+
directly from the raw ciphersuite bytes.
14936+
14937+
\param [in] first First byte of the hash and signature algorithm
14938+
\param [in] second Second byte of the hash and signature algorithm
14939+
\param [out] hashAlgo The enum wc_HashType of the MAC algorithm
14940+
\param [out] sigAlgo The enum Key_Sum of the authentication algorithm
14941+
14942+
\return 0 when info was correctly set
14943+
\return BAD_FUNC_ARG when either input paramters are NULL or the bytes
14944+
are not a recognized sigalg suite
14945+
14946+
_Example_
14947+
\code
14948+
enum wc_HashType hashAlgo;
14949+
enum Key_Sum sigAlgo;
14950+
14951+
wolfSSL_get_sigalg_info(hashSigAlgo[idx+0], hashSigAlgo[idx+1],
14952+
&hashAlgo, &sigAlgo);
14953+
14954+
if (sigAlgo == RSAk || sigAlgo == RSAPSSk)
14955+
haveRSA = 1;
14956+
else if (sigAlgo == ECDSAk)
14957+
haveECC = 1;
14958+
\endcode
14959+
14960+
\sa wolfSSL_get_client_suites_sigalgs
14961+
\sa wolfSSL_get_ciphersuite_info
14962+
*/
14963+
int wolfSSL_get_sigalg_info(byte first, byte second,
14964+
int* hashAlgo, int* sigAlgo);

src/internal.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4236,7 +4236,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
42364236
* hashalgo The hash algorithm.
42374237
* hsType The signature type.
42384238
*/
4239-
static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
4239+
void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
42404240
{
42414241
*hsType = invalid_sa_algo;
42424242
switch (input[0]) {
@@ -4324,7 +4324,7 @@ static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsTy
43244324
#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
43254325
defined(HAVE_CURVE448) || (!defined(NO_RSA) && defined(WC_RSA_PSS))
43264326

4327-
static enum wc_HashType HashAlgoToType(int hashAlgo)
4327+
enum wc_HashType HashAlgoToType(int hashAlgo)
43284328
{
43294329
switch (hashAlgo) {
43304330
#ifdef WOLFSSL_SHA512
@@ -11224,23 +11224,11 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
1122411224
#endif /* WOLFSSL_NO_TLS12 */
1122511225

1122611226
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
11227-
/* cipher requirements */
11228-
enum {
11229-
REQUIRES_RSA,
11230-
REQUIRES_DHE,
11231-
REQUIRES_ECC,
11232-
REQUIRES_ECC_STATIC,
11233-
REQUIRES_PSK,
11234-
REQUIRES_RSA_SIG,
11235-
REQUIRES_AEAD
11236-
};
11237-
11238-
1123911227

1124011228
/* Does this cipher suite (first, second) have the requirement
1124111229
an ephemeral key exchange will still require the key for signing
1124211230
the key exchange so ECDHE_RSA requires an rsa key thus rsa_kea */
11243-
static int CipherRequires(byte first, byte second, int requirement)
11231+
int CipherRequires(byte first, byte second, int requirement)
1124411232
{
1124511233

1124611234
(void)requirement;
@@ -35435,6 +35423,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
3543535423
#endif
3543635424

3543735425
#ifdef OPENSSL_EXTRA
35426+
ssl->clSuites = clSuites;
3543835427
/* Give user last chance to provide a cert for cipher selection */
3543935428
if (ret == 0 && ssl->ctx->certSetupCb != NULL)
3544035429
ret = CertSetupCbWrapper(ssl);
@@ -35458,7 +35447,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
3545835447
#endif
3545935448

3546035449
out:
35461-
35450+
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
35451+
ssl->clSuites = NULL;
35452+
#endif
3546235453
#ifdef WOLFSSL_SMALL_STACK
3546335454
if (clSuites != NULL)
3546435455
XFREE(clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);

src/ssl.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16303,6 +16303,163 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
1630316303
ctx->certSetupCbArg = arg;
1630416304
}
1630516305

16306+
int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
16307+
const byte** suites, word16* suiteSz,
16308+
const byte** hashSigAlgo, word16* hashSigAlgoSz)
16309+
{
16310+
WOLFSSL_ENTER("wolfSSL_get_client_suites_sigalgs");
16311+
16312+
if (suites != NULL)
16313+
*suites = NULL;
16314+
if (suiteSz != NULL)
16315+
*suiteSz = 0;
16316+
if (hashSigAlgo != NULL)
16317+
*hashSigAlgo = NULL;
16318+
if (hashSigAlgoSz != NULL)
16319+
*hashSigAlgoSz = 0;
16320+
16321+
if (ssl != NULL && ssl->clSuites != NULL) {
16322+
if (suites != NULL && suiteSz != NULL) {
16323+
*suites = ssl->clSuites->suites;
16324+
*suiteSz = ssl->clSuites->suiteSz;
16325+
}
16326+
if (hashSigAlgo != NULL && hashSigAlgoSz != NULL) {
16327+
*hashSigAlgo = ssl->clSuites->hashSigAlgo;
16328+
*hashSigAlgoSz = ssl->clSuites->hashSigAlgoSz;
16329+
}
16330+
return WOLFSSL_SUCCESS;
16331+
}
16332+
return WOLFSSL_FAILURE;
16333+
}
16334+
WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
16335+
byte second)
16336+
{
16337+
WOLFSSL_CIPHERSUITE_INFO info;
16338+
info.rsaAuth = (byte)(CipherRequires(first, second, REQUIRES_RSA) ||
16339+
CipherRequires(first, second, REQUIRES_RSA_SIG));
16340+
info.eccAuth = (byte)(CipherRequires(first, second, REQUIRES_ECC) ||
16341+
/* Static ECC ciphers may require RSA for authentication */
16342+
(CipherRequires(first, second, REQUIRES_ECC_STATIC) &&
16343+
!CipherRequires(first, second, REQUIRES_RSA_SIG)));
16344+
info.eccStatic =
16345+
(byte)CipherRequires(first, second, REQUIRES_ECC_STATIC);
16346+
info.psk = (byte)CipherRequires(first, second, REQUIRES_PSK);
16347+
return info;
16348+
}
16349+
16350+
/**
16351+
* @param first First byte of the hash and signature algorithm
16352+
* @param second Second byte of the hash and signature algorithm
16353+
* @param hashAlgo The enum wc_HashType of the MAC algorithm
16354+
* @param sigAlgo The enum Key_Sum of the authentication algorithm
16355+
*/
16356+
int wolfSSL_get_sigalg_info(byte first, byte second,
16357+
int* hashAlgo, int* sigAlgo)
16358+
{
16359+
byte input[2];
16360+
byte hashType;
16361+
byte sigType;
16362+
16363+
if (hashAlgo == NULL || sigAlgo == NULL)
16364+
return BAD_FUNC_ARG;
16365+
16366+
input[0] = first;
16367+
input[1] = second;
16368+
DecodeSigAlg(input, &hashType, &sigType);
16369+
16370+
/* cast so that compiler reminds us of unimplemented values */
16371+
switch ((enum SignatureAlgorithm)sigType) {
16372+
case anonymous_sa_algo:
16373+
*sigAlgo = (enum Key_Sum)0;
16374+
break;
16375+
case rsa_sa_algo:
16376+
*sigAlgo = RSAk;
16377+
break;
16378+
case dsa_sa_algo:
16379+
*sigAlgo = DSAk;
16380+
break;
16381+
case ecc_dsa_sa_algo:
16382+
*sigAlgo = ECDSAk;
16383+
break;
16384+
case rsa_pss_sa_algo:
16385+
*sigAlgo = RSAPSSk;
16386+
break;
16387+
case ed25519_sa_algo:
16388+
*sigAlgo = ED25519k;
16389+
break;
16390+
case rsa_pss_pss_algo:
16391+
*sigAlgo = RSAPSSk;
16392+
break;
16393+
case ed448_sa_algo:
16394+
*sigAlgo = ED448k;
16395+
break;
16396+
case falcon_level1_sa_algo:
16397+
*sigAlgo = FALCON_LEVEL1k;
16398+
break;
16399+
case falcon_level5_sa_algo:
16400+
*sigAlgo = FALCON_LEVEL5k;
16401+
break;
16402+
case dilithium_level2_sa_algo:
16403+
*sigAlgo = DILITHIUM_LEVEL2k;
16404+
break;
16405+
case dilithium_level3_sa_algo:
16406+
*sigAlgo = DILITHIUM_LEVEL3k;
16407+
break;
16408+
case dilithium_level5_sa_algo:
16409+
*sigAlgo = DILITHIUM_LEVEL5k;
16410+
break;
16411+
case sm2_sa_algo:
16412+
*sigAlgo = SM2k;
16413+
break;
16414+
case invalid_sa_algo:
16415+
default:
16416+
*hashAlgo = WC_HASH_TYPE_NONE;
16417+
*sigAlgo = 0;
16418+
return BAD_FUNC_ARG;
16419+
}
16420+
16421+
/* cast so that compiler reminds us of unimplemented values */
16422+
switch((enum wc_MACAlgorithm)hashType) {
16423+
case no_mac:
16424+
case rmd_mac: /* Don't have a RIPEMD type in wc_HashType */
16425+
*hashAlgo = WC_HASH_TYPE_NONE;
16426+
break;
16427+
case md5_mac:
16428+
*hashAlgo = WC_HASH_TYPE_MD5;
16429+
break;
16430+
case sha_mac:
16431+
*hashAlgo = WC_HASH_TYPE_SHA;
16432+
break;
16433+
case sha224_mac:
16434+
*hashAlgo = WC_HASH_TYPE_SHA224;
16435+
break;
16436+
case sha256_mac:
16437+
*hashAlgo = WC_HASH_TYPE_SHA256;
16438+
break;
16439+
case sha384_mac:
16440+
*hashAlgo = WC_HASH_TYPE_SHA384;
16441+
break;
16442+
case sha512_mac:
16443+
*hashAlgo = WC_HASH_TYPE_SHA512;
16444+
break;
16445+
case blake2b_mac:
16446+
*hashAlgo = WC_HASH_TYPE_BLAKE2B;
16447+
break;
16448+
case sm3_mac:
16449+
#ifdef WOLFSSL_SM3
16450+
*hashAlgo = WC_HASH_TYPE_SM3;
16451+
#else
16452+
*hashAlgo = WC_HASH_TYPE_NONE;
16453+
#endif
16454+
break;
16455+
default:
16456+
*hashAlgo = WC_HASH_TYPE_NONE;
16457+
*sigAlgo = 0;
16458+
return BAD_FUNC_ARG;
16459+
}
16460+
return 0;
16461+
}
16462+
1630616463
/**
1630716464
* Internal wrapper for calling certSetupCb
1630816465
* @param ssl The SSL/TLS Object

src/tls13.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5617,6 +5617,11 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
56175617
if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo);
56185618
#endif
56195619

5620+
#ifdef OPENSSL_EXTRA
5621+
if ((ret = CertSetupCbWrapper(ssl)) != 0)
5622+
return ret;
5623+
#endif
5624+
56205625
if (OPAQUE8_LEN > size)
56215626
return BUFFER_ERROR;
56225627

@@ -6594,6 +6599,9 @@ static void FreeDch13Args(WOLFSSL* ssl, void* pArgs)
65946599
XFREE(args->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);
65956600
args->clSuites = NULL;
65966601
}
6602+
#ifdef OPENSSL_EXTRA
6603+
ssl->clSuites = NULL;
6604+
#endif
65976605
}
65986606

65996607
int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
@@ -6978,6 +6986,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
69786986

69796987
case TLS_ASYNC_DO:
69806988
{
6989+
#ifdef OPENSSL_EXTRA
6990+
ssl->clSuites = args->clSuites;
6991+
if ((ret = CertSetupCbWrapper(ssl)) != 0)
6992+
goto exit_dch;
6993+
#endif
69816994
#ifndef NO_CERTS
69826995
if (!args->usingPSK) {
69836996
if ((ret = MatchSuite(ssl, args->clSuites)) < 0) {
@@ -8244,11 +8257,6 @@ static int SendTls13Certificate(WOLFSSL* ssl)
82448257
listSz = 0;
82458258
}
82468259
else {
8247-
#ifdef OPENSSL_EXTRA
8248-
if ((ret = CertSetupCbWrapper(ssl)) != 0)
8249-
return ret;
8250-
#endif
8251-
82528260
if (!ssl->buffers.certificate) {
82538261
WOLFSSL_MSG("Send Cert missing certificate buffer");
82548262
return BUFFER_ERROR;

0 commit comments

Comments
 (0)