@@ -25888,6 +25888,153 @@ int SendCertificate(WOLFSSL* ssl)
2588825888
2588925889
2589025890#if !defined(NO_TLS)
25891+ /* Returns the certificate_types this server advertises in its
25892+ * CertificateRequest. The list is broader than the negotiated cipher suite's
25893+ * own signature algorithm so a client may authenticate with a certificate of
25894+ * a different type (e.g. an RSA client on an ECDHE-ECDSA suite). */
25895+ WC_MAYBE_UNUSED static int GetServerCertReqCertTypes(const WOLFSSL* ssl,
25896+ byte* certTypes)
25897+ {
25898+ int n = 0;
25899+ (void)ssl;
25900+ (void)certTypes;
25901+ #ifdef HAVE_ECC
25902+ if ((ssl->options.cipherSuite0 == ECC_BYTE ||
25903+ ssl->options.cipherSuite0 == CHACHA_BYTE) &&
25904+ ssl->specs.sig_algo == ecc_dsa_sa_algo) {
25905+ certTypes[n++] = ecdsa_sign;
25906+ #ifndef NO_RSA
25907+ certTypes[n++] = rsa_sign;
25908+ #endif
25909+ }
25910+ else
25911+ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) && \
25912+ (defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_GCM) || \
25913+ defined(WOLFSSL_SM4_CCM))
25914+ if (ssl->options.cipherSuite0 == SM_BYTE && (0
25915+ #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
25916+ || ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
25917+ #endif
25918+ #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3
25919+ || ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3
25920+ #endif
25921+ #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3
25922+ || ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3
25923+ #endif
25924+ )) {
25925+ certTypes[n++] = ecdsa_sign;
25926+ }
25927+ else
25928+ #endif
25929+ #endif /* HAVE_ECC */
25930+ {
25931+ #ifndef NO_RSA
25932+ certTypes[n++] = rsa_sign;
25933+ #endif
25934+ #ifdef HAVE_ECC
25935+ certTypes[n++] = ecdsa_sign;
25936+ #endif
25937+ }
25938+ return n;
25939+ }
25940+
25941+ /* Returns the set of sig families covered by the given hash/sig algorithm
25942+ * list, as a bitmask of SIG_* values. Uses DecodeSigAlg so the NEW_SA_MAJOR
25943+ * encoding (ED25519/ED448/RSA-PSS-PSS/brainpool) is classified correctly. */
25944+ WC_MAYBE_UNUSED static int HashSigAlgoCoverage(const byte* hashSigAlgo,
25945+ word16 hashSigAlgoSz)
25946+ {
25947+ int coverage = 0;
25948+ word16 j;
25949+ byte hashAlgo;
25950+ byte sigAlgo;
25951+ for (j = 0; (j + 1) < hashSigAlgoSz; j += HELLO_EXT_SIGALGO_SZ) {
25952+ DecodeSigAlg(&hashSigAlgo[j], &hashAlgo, &sigAlgo);
25953+ (void)hashAlgo;
25954+ switch (sigAlgo) {
25955+ case rsa_sa_algo:
25956+ #ifdef WC_RSA_PSS
25957+ case rsa_pss_sa_algo:
25958+ case rsa_pss_pss_algo:
25959+ #endif
25960+ coverage |= SIG_RSA;
25961+ break;
25962+ #ifdef HAVE_ECC
25963+ case ecc_dsa_sa_algo:
25964+ #ifdef HAVE_ECC_BRAINPOOL
25965+ case ecc_brainpool_sa_algo:
25966+ #endif
25967+ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
25968+ case sm2_sa_algo:
25969+ #endif
25970+ coverage |= SIG_ECDSA;
25971+ break;
25972+ #endif
25973+ default:
25974+ break;
25975+ }
25976+ }
25977+ return coverage;
25978+ }
25979+
25980+ /* Builds the signature_algorithms this server advertises in its
25981+ * CertificateRequest. Respects a user-configured suites->hashSigAlgo (e.g.
25982+ * via wolfSSL_set1_sigalgs_list) and only broadens the list when one of the
25983+ * advertised certificate_types has no matching signature algorithm in the
25984+ * configured list. The result is written to the caller's buffer; no SSL
25985+ * state is modified. */
25986+ WC_MAYBE_UNUSED static void GetServerCertReqHashSigAlgo(const WOLFSSL* ssl,
25987+ byte* hashSigAlgo, word16* hashSigAlgoSz)
25988+ {
25989+ const Suites* suites = WOLFSSL_SUITES(ssl);
25990+ byte certTypes[MAX_CERT_REQ_CERT_TYPE_CNT];
25991+ int typeTotal;
25992+ int need = 0;
25993+ int have;
25994+ int j;
25995+ word16 localSz = 0;
25996+
25997+ typeTotal = GetServerCertReqCertTypes(ssl, certTypes);
25998+ for (j = 0; j < typeTotal; j++) {
25999+ if (certTypes[j] == rsa_sign)
26000+ need |= SIG_RSA;
26001+ else if (certTypes[j] == ecdsa_sign)
26002+ need |= SIG_ECDSA;
26003+ }
26004+ have = HashSigAlgoCoverage(suites->hashSigAlgo, suites->hashSigAlgoSz);
26005+
26006+ if ((need & ~have) != 0) {
26007+ /* The configured list is missing signature algorithms for at least
26008+ * one of the advertised certificate_types. Build a broader list
26009+ * locally that covers every advertised type. */
26010+ InitSuitesHashSigAlgo(hashSigAlgo, need | have, 1, 0,
26011+ ssl->buffers.keySz, &localSz);
26012+ *hashSigAlgoSz = localSz;
26013+ return;
26014+ }
26015+
26016+ XMEMCPY(hashSigAlgo, suites->hashSigAlgo, suites->hashSigAlgoSz);
26017+ *hashSigAlgoSz = suites->hashSigAlgoSz;
26018+ }
26019+
26020+ /* Returns 1 if algo (2 bytes) is in the server's CertificateRequest
26021+ * signature_algorithms list, 0 otherwise. Used to validate the client's
26022+ * CertificateVerify against what we actually advertised. */
26023+ WC_MAYBE_UNUSED static int InServerCertReqHashSigAlgo(const WOLFSSL* ssl,
26024+ const byte* algo)
26025+ {
26026+ byte list[WOLFSSL_MAX_SIGALGO];
26027+ word16 listSz = 0;
26028+ word16 j;
26029+
26030+ GetServerCertReqHashSigAlgo(ssl, list, &listSz);
26031+ for (j = 0; (j + 1) < listSz; j += HELLO_EXT_SIGALGO_SZ) {
26032+ if (XMEMCMP(&list[j], algo, HELLO_EXT_SIGALGO_SZ) == 0)
26033+ return 1;
26034+ }
26035+ return 0;
26036+ }
26037+
2589126038/* handle generation of certificate_request (13) */
2589226039int SendCertificateRequest(WOLFSSL* ssl)
2589326040{
@@ -25899,16 +26046,24 @@ int SendCertificateRequest(WOLFSSL* ssl)
2589926046#ifndef WOLFSSL_NO_CA_NAMES
2590026047 WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
2590126048#endif
25902- const Suites* suites = WOLFSSL_SUITES(ssl);
25903-
25904- int typeTotal = 1; /* only 1 for now */
25905- int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
26049+ byte certTypes[MAX_CERT_REQ_CERT_TYPE_CNT];
26050+ int typeTotal;
26051+ int t;
26052+ byte localHashSigAlgo[WOLFSSL_MAX_SIGALGO];
26053+ word16 localHashSigAlgoSz = 0;
26054+ int reqSz;
2590626055
2590726056 WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
2590826057 WOLFSSL_ENTER("SendCertificateRequest");
2590926058
26059+ typeTotal = GetServerCertReqCertTypes(ssl, certTypes);
26060+ if (IsAtLeastTLSv1_2(ssl))
26061+ GetServerCertReqHashSigAlgo(ssl, localHashSigAlgo, &localHashSigAlgoSz);
26062+
26063+ reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
26064+
2591026065 if (IsAtLeastTLSv1_2(ssl))
25911- reqSz += LENGTH_SZ + suites->hashSigAlgoSz ;
26066+ reqSz += LENGTH_SZ + localHashSigAlgoSz ;
2591226067
2591326068#ifndef WOLFSSL_NO_CA_NAMES
2591426069 /* Certificate Authorities */
@@ -25961,43 +26116,16 @@ int SendCertificateRequest(WOLFSSL* ssl)
2596126116
2596226117 /* write to output */
2596326118 output[i++] = (byte)typeTotal; /* # of types */
25964- #ifdef HAVE_ECC
25965- if ((ssl->options.cipherSuite0 == ECC_BYTE ||
25966- ssl->options.cipherSuite0 == CHACHA_BYTE) &&
25967- ssl->specs.sig_algo == ecc_dsa_sa_algo) {
25968- output[i++] = ecdsa_sign;
25969- }
25970- else
25971- #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) && \
25972- (defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_GCM) || \
25973- defined(WOLFSSL_SM4_CCM))
25974- if (ssl->options.cipherSuite0 == SM_BYTE && (0
25975- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
25976- || ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
25977- #endif
25978- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3
25979- || ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3
25980- #endif
25981- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3
25982- || ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3
25983- #endif
25984- )) {
25985- output[i++] = ecdsa_sign;
25986- }
25987- else
25988- #endif
25989- #endif /* HAVE_ECC */
25990- {
25991- output[i++] = rsa_sign;
25992- }
26119+ for (t = 0; t < typeTotal; t++)
26120+ output[i++] = certTypes[t];
2599326121
2599426122 /* supported hash/sig */
2599526123 if (IsAtLeastTLSv1_2(ssl)) {
25996- c16toa(suites->hashSigAlgoSz , &output[i]);
26124+ c16toa(localHashSigAlgoSz , &output[i]);
2599726125 i += OPAQUE16_LEN;
2599826126
25999- XMEMCPY(&output[i], suites->hashSigAlgo, suites->hashSigAlgoSz );
26000- i += suites->hashSigAlgoSz ;
26127+ XMEMCPY(&output[i], localHashSigAlgo, localHashSigAlgoSz );
26128+ i += localHashSigAlgoSz ;
2600126129 }
2600226130
2600326131 /* Certificate Authorities */
@@ -39067,9 +39195,9 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
3906739195 ERROR_OUT(BUFFER_ERROR, exit_dcv);
3906839196 }
3906939197
39070- /* Check if hashSigAlgo in CertificateVerify is supported
39071- * in our ssl->suites or ssl->ctx->suites . */
39072- if (!SupportedHashSigAlgo (ssl, &input[args->idx])) {
39198+ /* Check the algorithm in CertificateVerify against the
39199+ * list we actually advertised in our CertificateRequest . */
39200+ if (!InServerCertReqHashSigAlgo (ssl, &input[args->idx])) {
3907339201 WOLFSSL_MSG("Signature algorithm was not in "
3907439202 "CertificateRequest");
3907539203 ERROR_OUT(INVALID_PARAMETER, exit_dcv);
0 commit comments