Skip to content

Commit eb8ba61

Browse files
committed
Support TLS 1.3 ECC Brainpool authentication
This also fixes TLS 1.2 authentication to only succeed in case the brainpool curve was present in the supported_groups extension.
1 parent a462398 commit eb8ba61

7 files changed

Lines changed: 196 additions & 40 deletions

File tree

src/internal.c

Lines changed: 110 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,6 +3312,23 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo,
33123312
#endif
33133313
}
33143314
else
3315+
#endif
3316+
#ifdef HAVE_ECC_BRAINPOOL
3317+
if (sigAlgo == ecc_brainpool_sa_algo) {
3318+
if (macAlgo == sha512_mac) {
3319+
ADD_HASH_SIG_ALGO(hashSigAlgo, inOutIdx, NEW_SA_MAJOR,
3320+
ECDSA_BRAINPOOLP512R1TLS13_SHA512_MINOR);
3321+
}
3322+
else if (macAlgo == sha384_mac) {
3323+
ADD_HASH_SIG_ALGO(hashSigAlgo, inOutIdx, NEW_SA_MAJOR,
3324+
ECDSA_BRAINPOOLP384R1TLS13_SHA384_MINOR);
3325+
}
3326+
else if (macAlgo == sha256_mac) {
3327+
ADD_HASH_SIG_ALGO(hashSigAlgo, inOutIdx, NEW_SA_MAJOR,
3328+
ECDSA_BRAINPOOLP256R1TLS13_SHA256_MINOR);
3329+
}
3330+
}
3331+
else
33153332
#endif
33163333
{
33173334
ADD_HASH_SIG_ALGO(hashSigAlgo, inOutIdx, macAlgo, sigAlgo);
@@ -3320,11 +3337,12 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo,
33203337
}
33213338

33223339
void InitSuitesHashSigAlgo(byte* hashSigAlgo, int haveSig, int tls1_2,
3323-
int keySz, word16* len)
3340+
int tls1_3, int keySz, word16* len)
33243341
{
33253342
word16 idx = 0;
33263343

33273344
(void)tls1_2;
3345+
(void)tls1_3;
33283346
(void)keySz;
33293347

33303348
#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
@@ -3333,14 +3351,32 @@ void InitSuitesHashSigAlgo(byte* hashSigAlgo, int haveSig, int tls1_2,
33333351
#ifdef WOLFSSL_SHA512
33343352
AddSuiteHashSigAlgo(hashSigAlgo, sha512_mac, ecc_dsa_sa_algo, keySz,
33353353
&idx);
3354+
#ifdef HAVE_ECC_BRAINPOOL
3355+
if (tls1_3) {
3356+
AddSuiteHashSigAlgo(hashSigAlgo, sha512_mac, ecc_brainpool_sa_algo,
3357+
keySz, &idx);
3358+
}
3359+
#endif
33363360
#endif
33373361
#ifdef WOLFSSL_SHA384
33383362
AddSuiteHashSigAlgo(hashSigAlgo, sha384_mac, ecc_dsa_sa_algo, keySz,
33393363
&idx);
3364+
#ifdef HAVE_ECC_BRAINPOOL
3365+
if (tls1_3) {
3366+
AddSuiteHashSigAlgo(hashSigAlgo, sha384_mac, ecc_brainpool_sa_algo,
3367+
keySz, &idx);
3368+
}
3369+
#endif
33403370
#endif
33413371
#ifndef NO_SHA256
33423372
AddSuiteHashSigAlgo(hashSigAlgo, sha256_mac, ecc_dsa_sa_algo, keySz,
33433373
&idx);
3374+
#ifdef HAVE_ECC_BRAINPOOL
3375+
if (tls1_3) {
3376+
AddSuiteHashSigAlgo(hashSigAlgo, sha256_mac, ecc_brainpool_sa_algo,
3377+
keySz, &idx);
3378+
}
3379+
#endif
33443380
#endif
33453381
#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
33463382
defined(WOLFSSL_ALLOW_TLS_SHA1))
@@ -3465,9 +3501,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
34653501
word16 idx = 0;
34663502
int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
34673503
int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
3468-
#ifdef WOLFSSL_TLS13
34693504
int tls1_3 = IsAtLeastTLSv1_3(pv);
3470-
#endif
34713505
int dtls = 0;
34723506
int haveRSAsig = 1;
34733507

@@ -3484,6 +3518,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
34843518

34853519
(void)tls; /* shut up compiler */
34863520
(void)tls1_2;
3521+
(void)tls1_3;
34873522
(void)dtls;
34883523
(void)haveDH;
34893524
(void)havePSK;
@@ -4511,8 +4546,8 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
45114546
suites->suiteSz = idx;
45124547

45134548
if (suites->hashSigAlgoSz == 0) {
4514-
InitSuitesHashSigAlgo(suites->hashSigAlgo, SIG_ALL, tls1_2, keySz,
4515-
&suites->hashSigAlgoSz);
4549+
InitSuitesHashSigAlgo(suites->hashSigAlgo, SIG_ALL, tls1_2, tls1_3,
4550+
keySz, &suites->hashSigAlgoSz);
45164551
}
45174552

45184553
/* Moved to the end as we set some of the vars but never use them */
@@ -4571,6 +4606,22 @@ void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
45714606
*hashAlgo = PSS_PSS_HASH_TO_MAC(input[1]);
45724607
}
45734608
else
4609+
#endif
4610+
#ifdef HAVE_ECC_BRAINPOOL
4611+
/* RFC 8734 TLS 1.3 Brainpool curves */
4612+
if (input[1] == ECDSA_BRAINPOOLP256R1TLS13_SHA256_MINOR) {
4613+
*hsType = ecc_brainpool_sa_algo;
4614+
*hashAlgo = sha256_mac;
4615+
}
4616+
else if (input[1] == ECDSA_BRAINPOOLP384R1TLS13_SHA384_MINOR) {
4617+
*hsType = ecc_brainpool_sa_algo;
4618+
*hashAlgo = sha384_mac;
4619+
}
4620+
else if (input[1] == ECDSA_BRAINPOOLP512R1TLS13_SHA512_MINOR) {
4621+
*hsType = ecc_brainpool_sa_algo;
4622+
*hashAlgo = sha512_mac;
4623+
}
4624+
else
45744625
#endif
45754626
{
45764627
*hsType = input[0];
@@ -28273,6 +28324,7 @@ static int ParseCipherList(Suites* suites,
2827328324
word16 haveSHA1 = 1; /* allowed by default if compiled in */
2827428325
word16 haveRC4 = 1; /* allowed by default if compiled in */
2827528326
#endif
28327+
int tls1_3 = 0;
2827628328
const int suiteSz = GetCipherNamesSize();
2827728329
const char* next = list;
2827828330

@@ -28598,6 +28650,7 @@ static int ParseCipherList(Suites* suites,
2859828650
(cipher_names[i].cipherSuite0 == ECC_BYTE &&
2859928651
(cipher_names[i].cipherSuite == TLS_SHA256_SHA256 ||
2860028652
cipher_names[i].cipherSuite == TLS_SHA384_SHA384))) {
28653+
tls1_3 = 1;
2860128654
#ifndef NO_RSA
2860228655
haveSig |= SIG_RSA;
2860328656
#endif
@@ -28701,8 +28754,8 @@ static int ParseCipherList(Suites* suites,
2870128754
#endif
2870228755
{
2870328756
suites->suiteSz = (word16)idx;
28704-
InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, keySz,
28705-
&suites->hashSigAlgoSz);
28757+
InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, tls1_3,
28758+
keySz, &suites->hashSigAlgoSz);
2870628759
}
2870728760

2870828761
#ifdef HAVE_RENEGOTIATION_INDICATION
@@ -28775,6 +28828,7 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list,
2877528828
int haveFalconSig = 0;
2877628829
int haveDilithiumSig = 0;
2877728830
int haveAnon = 0;
28831+
int tls1_3 = 0;
2877828832

2877928833
if (suites == NULL || list == NULL) {
2878028834
WOLFSSL_MSG("SetCipherListFromBytes parameter error");
@@ -28834,6 +28888,7 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list,
2883428888
secondByte == TLS_SHA384_SHA384)) ||
2883528889
(firstByte == CIPHER_BYTE && (secondByte == TLS_SM4_GCM_SM3 ||
2883628890
secondByte == TLS_SM4_CCM_SM3))) {
28891+
tls1_3 = 1;
2883728892
#ifndef NO_RSA
2883828893
haveRSAsig = 1;
2883928894
#endif
@@ -28885,8 +28940,8 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list,
2888528940
haveSig |= haveFalconSig ? SIG_FALCON : 0;
2888628941
haveSig |= haveDilithiumSig ? SIG_DILITHIUM : 0;
2888728942
haveSig |= haveAnon ? SIG_ANON : 0;
28888-
InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, keySz,
28889-
&suites->hashSigAlgoSz);
28943+
InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, tls1_3,
28944+
keySz, &suites->hashSigAlgoSz);
2889028945
#ifdef HAVE_RENEGOTIATION_INDICATION
2889128946
if (ctx->method->side == WOLFSSL_CLIENT_END) {
2889228947
if (suites->suiteSz > WOLFSSL_MAX_SUITE_SZ - 2) {
@@ -29067,7 +29122,7 @@ int SetSuitesHashSigAlgo(Suites* suites, const char* list)
2906729122

2906829123
#endif /* OPENSSL_EXTRA */
2906929124

29070-
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS)
29125+
#if !defined(NO_TLS) && (!defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS))
2907129126
static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo)
2907229127
{
2907329128
#ifdef HAVE_ED25519
@@ -29134,6 +29189,41 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo)
2913429189
if (sigAlgo == rsa_pss_sa_algo)
2913529190
return 1;
2913629191
}
29192+
#endif
29193+
#ifdef HAVE_ECC_BRAINPOOL
29194+
if ((ssl->pkCurveOID == ECC_BRAINPOOLP256R1_OID) ||
29195+
(ssl->pkCurveOID == ECC_BRAINPOOLP384R1_OID) ||
29196+
(ssl->pkCurveOID == ECC_BRAINPOOLP512R1_OID)) {
29197+
if (IsAtLeastTLSv1_3(ssl->version)) {
29198+
/* Certificate has an ECC Brainpool key, only match with the
29199+
* specified ECDSA brainpool signature algorithms for TLS 1.3 */
29200+
return sigAlgo == ecc_brainpool_sa_algo;
29201+
}
29202+
else {
29203+
/* Certificate has an ECC Brainpool key, match with ECDSA in TLS 1.2
29204+
* case, but only when the related Brainpool curve is present in
29205+
* the supported_groups extension. */
29206+
if (ssl->pkCurveOID == ECC_BRAINPOOLP256R1_OID &&
29207+
TLSX_SupportedCurve_IsSupported(ssl,
29208+
WOLFSSL_ECC_BRAINPOOLP256R1)) {
29209+
return sigAlgo == ecc_dsa_sa_algo;
29210+
}
29211+
else if (ssl->pkCurveOID == ECC_BRAINPOOLP384R1_OID &&
29212+
TLSX_SupportedCurve_IsSupported(ssl,
29213+
WOLFSSL_ECC_BRAINPOOLP384R1)) {
29214+
return sigAlgo == ecc_dsa_sa_algo;
29215+
}
29216+
else if (ssl->pkCurveOID == ECC_BRAINPOOLP512R1_OID &&
29217+
TLSX_SupportedCurve_IsSupported(ssl,
29218+
WOLFSSL_ECC_BRAINPOOLP512R1)) {
29219+
return sigAlgo == ecc_dsa_sa_algo;
29220+
}
29221+
else {
29222+
/* Curve not supported in supported_groups extension. */
29223+
return 0;
29224+
}
29225+
}
29226+
}
2913729227
#endif
2913829228
/* Signature algorithm matches certificate. */
2913929229
return sigAlgo == ssl->options.sigAlgo;
@@ -29299,6 +29389,15 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz,
2929929389
break;
2930029390
}
2930129391
#endif /* HAVE_DILITHIUM */
29392+
#if defined(HAVE_ECC_BRAINPOOL)
29393+
if (ssl->pkCurveOID == ECC_BRAINPOOLP256R1_OID ||
29394+
ssl->pkCurveOID == ECC_BRAINPOOLP384R1_OID ||
29395+
ssl->pkCurveOID == ECC_BRAINPOOLP512R1_OID) {
29396+
/* Matched ECC Brainpool. Set sigAlgo to "normal" ECDSA here
29397+
* for compatibility with TLS 1.2. */
29398+
sigAlgo = ecc_dsa_sa_algo;
29399+
}
29400+
#endif
2930229401

2930329402
#if defined(WOLFSSL_ECDSA_MATCH_HASH) && defined(USE_ECDSA_KEYSZ_HASH_ALGO)
2930429403
#error "WOLFSSL_ECDSA_MATCH_HASH and USE_ECDSA_KEYSZ_HASH_ALGO cannot "
@@ -29439,7 +29538,7 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz,
2943929538

2944029539
return ret;
2944129540
}
29442-
#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */
29541+
#endif /* !NO_TLS && (!defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS)) */
2944329542

2944429543
#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
2944529544

src/ssl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12442,6 +12442,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
1244212442
*sigAlgo = DSAk;
1244312443
break;
1244412444
case ecc_dsa_sa_algo:
12445+
case ecc_brainpool_sa_algo:
1244512446
*sigAlgo = ECDSAk;
1244612447
break;
1244712448
case rsa_pss_sa_algo:
@@ -18367,6 +18368,7 @@ static int SaToNid(byte sa, int* nid)
1836718368
*nid = WC_NID_dsa;
1836818369
break;
1836918370
case ecc_dsa_sa_algo:
18371+
case ecc_brainpool_sa_algo:
1837018372
*nid = WC_NID_X9_62_id_ecPublicKey;
1837118373
break;
1837218374
case rsa_pss_sa_algo:

src/tls.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5332,6 +5332,31 @@ int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl)
53325332
}
53335333
#endif /* HAVE_FFDHE && !WOLFSSL_NO_TLS12 */
53345334

5335+
/* Check if the given curve is present in the supported groups extension.
5336+
*
5337+
* ssl SSL/TLS object.
5338+
* name The curve name to check.
5339+
* returns 1 if present, 0 otherwise.
5340+
*/
5341+
int TLSX_SupportedCurve_IsSupported(WOLFSSL* ssl, word16 name)
5342+
{
5343+
TLSX* extension;
5344+
SupportedCurve* curve;
5345+
5346+
extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
5347+
if (extension == NULL)
5348+
return 0;
5349+
5350+
curve = (SupportedCurve*)extension->data;
5351+
while (curve != NULL) {
5352+
if (curve->name == name)
5353+
return 1;
5354+
curve = curve->next;
5355+
}
5356+
5357+
return 0;
5358+
}
5359+
53355360
#endif /* !NO_WOLFSSL_SERVER */
53365361

53375362
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)

src/tls13.c

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7786,12 +7786,12 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
77867786
return SIDE_ERROR;
77877787

77887788
/* Get the length of the hashSigAlgo buffer */
7789-
InitSuitesHashSigAlgo(NULL, SIG_ALL, 1, ssl->buffers.keySz,
7789+
InitSuitesHashSigAlgo(NULL, SIG_ALL, 1, 1, ssl->buffers.keySz,
77907790
&hashSigAlgoSz);
77917791
sa = TLSX_SignatureAlgorithms_New(ssl, hashSigAlgoSz, ssl->heap);
77927792
if (sa == NULL)
77937793
return MEMORY_ERROR;
7794-
InitSuitesHashSigAlgo(sa->hashSigAlgo, SIG_ALL, 1, ssl->buffers.keySz,
7794+
InitSuitesHashSigAlgo(sa->hashSigAlgo, SIG_ALL, 1, 1, ssl->buffers.keySz,
77957795
&hashSigAlgoSz);
77967796
ret = TLSX_Push(&ssl->extensions, TLSX_SIGNATURE_ALGORITHMS, sa, ssl->heap);
77977797
if (ret != 0) {
@@ -7898,8 +7898,22 @@ static WC_INLINE void EncodeSigAlg(const WOLFSSL * ssl, byte hashAlgo, byte hsTy
78987898
switch (hsType) {
78997899
#ifdef HAVE_ECC
79007900
case ecc_dsa_sa_algo:
7901-
output[0] = hashAlgo;
7902-
output[1] = ecc_dsa_sa_algo;
7901+
if (ssl->pkCurveOID == ECC_BRAINPOOLP256R1_OID) {
7902+
output[0] = NEW_SA_MAJOR;
7903+
output[1] = ECDSA_BRAINPOOLP256R1TLS13_SHA256_MINOR;
7904+
}
7905+
else if (ssl->pkCurveOID == ECC_BRAINPOOLP384R1_OID) {
7906+
output[0] = NEW_SA_MAJOR;
7907+
output[1] = ECDSA_BRAINPOOLP384R1TLS13_SHA384_MINOR;
7908+
}
7909+
else if (ssl->pkCurveOID == ECC_BRAINPOOLP512R1_OID) {
7910+
output[0] = NEW_SA_MAJOR;
7911+
output[1] = ECDSA_BRAINPOOLP512R1TLS13_SHA512_MINOR;
7912+
}
7913+
else {
7914+
output[0] = hashAlgo;
7915+
output[1] = ecc_dsa_sa_algo;
7916+
}
79037917
break;
79047918
#endif
79057919
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
@@ -8068,16 +8082,19 @@ static enum wc_MACAlgorithm GetNewSAHashAlgo(int typeIn)
80688082
switch (typeIn) {
80698083
case RSA_PSS_RSAE_SHA256_MINOR:
80708084
case RSA_PSS_PSS_SHA256_MINOR:
8085+
case ECDSA_BRAINPOOLP256R1TLS13_SHA256_MINOR:
80718086
return sha256_mac;
80728087

80738088
case RSA_PSS_RSAE_SHA384_MINOR:
80748089
case RSA_PSS_PSS_SHA384_MINOR:
8090+
case ECDSA_BRAINPOOLP384R1TLS13_SHA384_MINOR:
80758091
return sha384_mac;
80768092

80778093
case RSA_PSS_RSAE_SHA512_MINOR:
80788094
case RSA_PSS_PSS_SHA512_MINOR:
80798095
case ED25519_SA_MINOR:
80808096
case ED448_SA_MINOR:
8097+
case ECDSA_BRAINPOOLP512R1TLS13_SHA512_MINOR:
80818098
return sha512_mac;
80828099
default:
80838100
return no_mac;
@@ -8133,6 +8150,13 @@ static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo,
81338150
*hsType = ed448_sa_algo;
81348151
/* Hash performed as part of sign/verify operation. */
81358152
}
8153+
#endif
8154+
#ifdef HAVE_ECC_BRAINPOOL
8155+
else if ((input[1] == ECDSA_BRAINPOOLP256R1TLS13_SHA256_MINOR) ||
8156+
(input[1] == ECDSA_BRAINPOOLP384R1TLS13_SHA384_MINOR) ||
8157+
(input[1] == ECDSA_BRAINPOOLP512R1TLS13_SHA512_MINOR)) {
8158+
*hsType = ecc_dsa_sa_algo;
8159+
}
81368160
#endif
81378161
else
81388162
ret = INVALID_PARAMETER;
@@ -10564,17 +10588,12 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
1056410588
#ifdef HAVE_ECC
1056510589
if ((ssl->options.peerSigAlgo == ecc_dsa_sa_algo) &&
1056610590
(ssl->peerEccDsaKeyPresent)) {
10567-
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
10568-
if (ssl->options.peerSigAlgo != sm2_sa_algo)
10569-
#endif
10570-
{
10571-
ret = CreateECCEncodedSig(args->sigData,
10572-
args->sigDataSz, ssl->options.peerHashAlgo);
10573-
if (ret < 0)
10574-
goto exit_dcv;
10575-
args->sigDataSz = (word16)ret;
10576-
ret = 0;
10577-
}
10591+
ret = CreateECCEncodedSig(args->sigData,
10592+
args->sigDataSz, ssl->options.peerHashAlgo);
10593+
if (ret < 0)
10594+
goto exit_dcv;
10595+
args->sigDataSz = (word16)ret;
10596+
ret = 0;
1057810597
}
1057910598

1058010599
#ifdef WOLFSSL_DUAL_ALG_CERTS

0 commit comments

Comments
 (0)