Skip to content

Commit 7c2344c

Browse files
committed
Add API to get information about ciphersuites
1 parent fbd8996 commit 7c2344c

6 files changed

Lines changed: 205 additions & 28 deletions

File tree

doc/dox_comments/header_files/ssl.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14854,3 +14854,73 @@ 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] suites Raw and unfiltered list of client ciphersuites
14869+
\param [out] suiteSz Size of suites in bytes
14870+
\param [out] hashSigAlgo Raw and unfiltered list of client signature algorithms
14871+
\param [out] hashSigAlgoSz Size of hashSigAlgo in bytes
14872+
14873+
_Example_
14874+
\code
14875+
int certCB(WOLFSSL* ssl, void* arg)
14876+
{
14877+
const byte* suites = NULL;
14878+
word16 suiteSz = 0;
14879+
const byte* hashSigAlgo = NULL;
14880+
word16 hashSigAlgoSz = 0;
14881+
14882+
wolfSSL_get_client_suites_sigalgs(ssl, &suites, &suiteSz, &hashSigAlgo,
14883+
&hashSigAlgoSz);
14884+
14885+
// Choose certificate to load based on ciphersuites
14886+
}
14887+
14888+
WOLFSSL* ctx;
14889+
ctx = wolfSSL_CTX_new(wolfTLSv1_3_method_ex(NULL));
14890+
wolfSSL_CTX_set_cert_cb(ctx, certCB, NULL);
14891+
\endcode
14892+
14893+
\sa wolfSSL_new
14894+
\sa wolfSSL_free
14895+
*/
14896+
void wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
14897+
const byte** suites, word16* suiteSz,
14898+
const byte** hashSigAlgo, word16* hashSigAlgoSz);
14899+
14900+
/*!
14901+
\ingroup TLS
14902+
14903+
\brief This returns information about the ciphersuite directly from the
14904+
raw ciphersuite bytes.
14905+
14906+
\param [in] first First byte of the ciphersuite
14907+
\param [in] second Second byte of the ciphersuite
14908+
14909+
\return WOLFSSL_CIPHERSUITE_INFO A struct containing information about the
14910+
type of authentication used in the ciphersuite.
14911+
14912+
_Example_
14913+
\code
14914+
WOLFSSL_CIPHERSUITE_INFO info =
14915+
wolfSSL_get_ciphersuite_info(suites[0], suites[1]);
14916+
if (info.rsaAuth)
14917+
haveRSA = 1;
14918+
else if (info.eccAuth)
14919+
haveECC = 1;
14920+
\endcode
14921+
14922+
\sa wolfSSL_new
14923+
\sa wolfSSL_free
14924+
*/
14925+
WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
14926+
byte second);

src/internal.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11222,23 +11222,11 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
1122211222
#endif /* WOLFSSL_NO_TLS12 */
1122311223

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

1123811226
/* Does this cipher suite (first, second) have the requirement
1123911227
an ephemeral key exchange will still require the key for signing
1124011228
the key exchange so ECDHE_RSA requires an rsa key thus rsa_kea */
11241-
static int CipherRequires(byte first, byte second, int requirement)
11229+
int CipherRequires(byte first, byte second, int requirement)
1124211230
{
1124311231

1124411232
(void)requirement;

src/ssl.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16322,6 +16322,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
1632216322
}
1632316323
}
1632416324
}
16325+
WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
16326+
byte second)
16327+
{
16328+
WOLFSSL_CIPHERSUITE_INFO info;
16329+
info.rsaAuth = (byte)(CipherRequires(first, second, REQUIRES_RSA) ||
16330+
CipherRequires(first, second, REQUIRES_RSA_SIG));
16331+
info.eccAuth = (byte)(CipherRequires(first, second, REQUIRES_ECC) ||
16332+
/* Static ECC ciphers may require RSA for authentication */
16333+
(CipherRequires(first, second, REQUIRES_ECC_STATIC) &&
16334+
!CipherRequires(first, second, REQUIRES_RSA_SIG)));
16335+
info.eccStatic =
16336+
(byte)CipherRequires(first, second, REQUIRES_ECC_STATIC);
16337+
info.psk = (byte)CipherRequires(first, second, REQUIRES_PSK);
16338+
return info;
16339+
}
1632516340

1632616341
/**
1632716342
* Internal wrapper for calling certSetupCb

tests/api.c

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@
370370
defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) || \
371371
defined(WOLFSSL_TEST_STATIC_BUILD) || defined(WOLFSSL_DTLS) || \
372372
defined(HAVE_ECH) || defined(HAVE_EX_DATA) || !defined(NO_SESSION_CACHE) \
373-
|| !defined(WOLFSSL_NO_TLS12)
373+
|| !defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)
374374
/* for testing SSL_get_peer_cert_chain, or SESSION_TICKET_HINT_DEFAULT,
375375
* for setting authKeyIdSrc in WOLFSSL_X509, or testing DTLS sequence
376376
* number tracking */
@@ -44849,20 +44849,14 @@ static int test_wolfSSL_cert_cb_dyn_ciphers_certCB(WOLFSSL* ssl, void* arg)
4484944849
hashSigAlgoSz == 0)
4485044850
return 0;
4485144851

44852-
if (wolfSSL_GetVersion(ssl) != TLSv1_3_MINOR) {
44853-
for (idx = 0; idx < suiteSz; idx += 2) {
44854-
const char* cipherName = wolfSSL_get_cipher_name_from_suite(
44855-
suites[idx], suites[idx+1]);
44856-
if (cipherName == NULL)
44857-
return 0;
44858-
/* TLS 1.3 suites tell us nothing about the sigalg */
44859-
if (XSTRSTR(cipherName, "TLS13-") != NULL)
44860-
continue;
44861-
if (XSTRSTR(cipherName, "-RSA-") != NULL)
44862-
haveRSA = 1;
44863-
if (XSTRSTR(cipherName, "-ECDSA-") != NULL)
44864-
haveECC = 1;
44865-
}
44852+
for (idx = 0; idx < suiteSz; idx += 2) {
44853+
WOLFSSL_CIPHERSUITE_INFO info =
44854+
wolfSSL_get_ciphersuite_info(suites[idx], suites[idx+1]);
44855+
44856+
if (info.rsaAuth)
44857+
haveRSA = 1;
44858+
else if (info.eccAuth)
44859+
haveECC = 1;
4486644860
}
4486744861

4486844862
if (hashSigAlgoSz > 0) {
@@ -44998,6 +44992,96 @@ static int test_wolfSSL_cert_cb_dyn_ciphers(void)
4499844992
return EXPECT_RESULT();
4499944993
}
4500044994

44995+
static int test_wolfSSL_ciphersuite_auth(void)
44996+
{
44997+
EXPECT_DECLS;
44998+
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
44999+
WOLFSSL_CIPHERSUITE_INFO info;
45000+
45001+
(void)info;
45002+
45003+
#ifndef WOLFSSL_NO_TLS12
45004+
#ifdef HAVE_CHACHA
45005+
info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE,
45006+
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
45007+
ExpectIntEQ(info.rsaAuth, 1);
45008+
ExpectIntEQ(info.eccAuth, 0);
45009+
ExpectIntEQ(info.eccStatic, 0);
45010+
ExpectIntEQ(info.psk, 0);
45011+
45012+
info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE,
45013+
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
45014+
ExpectIntEQ(info.rsaAuth, 0);
45015+
ExpectIntEQ(info.eccAuth, 1);
45016+
ExpectIntEQ(info.eccStatic, 0);
45017+
ExpectIntEQ(info.psk, 0);
45018+
45019+
info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE,
45020+
TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256);
45021+
ExpectIntEQ(info.rsaAuth, 0);
45022+
ExpectIntEQ(info.eccAuth, 0);
45023+
ExpectIntEQ(info.eccStatic, 0);
45024+
ExpectIntEQ(info.psk, 1);
45025+
#endif
45026+
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
45027+
#ifndef NO_RSA
45028+
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
45029+
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
45030+
ExpectIntEQ(info.rsaAuth, 1);
45031+
ExpectIntEQ(info.eccAuth, 0);
45032+
ExpectIntEQ(info.eccStatic, 0);
45033+
ExpectIntEQ(info.psk, 0);
45034+
45035+
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
45036+
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA);
45037+
ExpectIntEQ(info.rsaAuth, 1);
45038+
ExpectIntEQ(info.eccAuth, 0);
45039+
ExpectIntEQ(info.eccStatic, 1);
45040+
ExpectIntEQ(info.psk, 0);
45041+
45042+
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
45043+
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA);
45044+
ExpectIntEQ(info.rsaAuth, 1);
45045+
ExpectIntEQ(info.eccAuth, 0);
45046+
ExpectIntEQ(info.eccStatic, 1);
45047+
ExpectIntEQ(info.psk, 0);
45048+
#endif
45049+
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
45050+
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
45051+
ExpectIntEQ(info.rsaAuth, 0);
45052+
ExpectIntEQ(info.eccAuth, 1);
45053+
ExpectIntEQ(info.eccStatic, 0);
45054+
ExpectIntEQ(info.psk, 0);
45055+
45056+
info = wolfSSL_get_ciphersuite_info(ECC_BYTE,
45057+
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA);
45058+
ExpectIntEQ(info.rsaAuth, 0);
45059+
ExpectIntEQ(info.eccAuth, 1);
45060+
ExpectIntEQ(info.eccStatic, 1);
45061+
ExpectIntEQ(info.psk, 0);
45062+
45063+
info = wolfSSL_get_ciphersuite_info(ECDHE_PSK_BYTE,
45064+
TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256);
45065+
ExpectIntEQ(info.rsaAuth, 0);
45066+
ExpectIntEQ(info.eccAuth, 0);
45067+
ExpectIntEQ(info.eccStatic, 0);
45068+
ExpectIntEQ(info.psk, 1);
45069+
#endif
45070+
#endif
45071+
45072+
#ifdef WOLFSSL_TLS13
45073+
info = wolfSSL_get_ciphersuite_info(TLS13_BYTE,
45074+
TLS_AES_128_GCM_SHA256);
45075+
ExpectIntEQ(info.rsaAuth, 0);
45076+
ExpectIntEQ(info.eccAuth, 0);
45077+
ExpectIntEQ(info.eccStatic, 0);
45078+
ExpectIntEQ(info.psk, 0);
45079+
#endif
45080+
45081+
#endif
45082+
return EXPECT_RESULT();
45083+
}
45084+
4500145085
static int test_wolfSSL_SESSION(void)
4500245086
{
4500345087
EXPECT_DECLS;
@@ -69183,6 +69267,7 @@ TEST_CASE testCases[] = {
6918369267
#endif
6918469268
TEST_DECL(test_wolfSSL_cert_cb),
6918569269
TEST_DECL(test_wolfSSL_cert_cb_dyn_ciphers),
69270+
TEST_DECL(test_wolfSSL_ciphersuite_auth),
6918669271
/* Can't memory test as tcp_connect aborts. */
6918769272
TEST_DECL(test_wolfSSL_SESSION),
6918869273
TEST_DECL(test_wolfSSL_SESSION_expire_downgrade),

wolfssl/internal.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6014,6 +6014,16 @@ enum ProvisionSide {
60146014
PROVISION_CLIENT_SERVER = 3
60156015
};
60166016

6017+
/* cipher requirements */
6018+
enum {
6019+
REQUIRES_RSA,
6020+
REQUIRES_DHE,
6021+
REQUIRES_ECC,
6022+
REQUIRES_ECC_STATIC,
6023+
REQUIRES_PSK,
6024+
REQUIRES_RSA_SIG,
6025+
REQUIRES_AEAD
6026+
};
60176027

60186028
static const byte kTlsClientStr[SIZEOF_SENDER+1] = { 0x43, 0x4C, 0x4E, 0x54, 0x00 }; /* CLNT */
60196029
static const byte kTlsServerStr[SIZEOF_SENDER+1] = { 0x53, 0x52, 0x56, 0x52, 0x00 }; /* SRVR */
@@ -6105,6 +6115,7 @@ WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree);
61056115
WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl);
61066116
WOLFSSL_LOCAL byte* GetOutputBuffer(WOLFSSL* ssl);
61076117

6118+
WOLFSSL_LOCAL int CipherRequires(byte first, byte second, int requirement);
61086119
WOLFSSL_LOCAL int VerifyClientSuite(word16 havePSK, byte cipherSuite0,
61096120
byte cipherSuite);
61106121

wolfssl/ssl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,14 @@ WOLFSSL_API void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx,
21242124
WOLFSSL_API void wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
21252125
const byte** suites, word16* suiteSz,
21262126
const byte** hashSigAlgo, word16* hashSigAlgoSz);
2127+
typedef struct WOLFSSL_CIPHERSUITE_INFO {
2128+
byte rsaAuth:1;
2129+
byte eccAuth:1;
2130+
byte eccStatic:1;
2131+
byte psk:1;
2132+
} WOLFSSL_CIPHERSUITE_INFO;
2133+
WOLFSSL_API WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
2134+
byte second);
21272135
WOLFSSL_LOCAL int CertSetupCbWrapper(WOLFSSL* ssl);
21282136

21292137
WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(

0 commit comments

Comments
 (0)