643 lines
25 KiB
Diff
643 lines
25 KiB
Diff
diff --git a/automation/abi-check/expected-report-libssl3.so.txt b/automation/abi-check/expected-report-libssl3.so.txt
|
|
--- a/automation/abi-check/expected-report-libssl3.so.txt
|
|
+++ b/automation/abi-check/expected-report-libssl3.so.txt
|
|
@@ -0,0 +1,24 @@
|
|
+
|
|
+1 function with some indirect sub-type change:
|
|
+
|
|
+ [C]'function SECStatus SSL_ConfigServerCert(PRFileDesc*, CERTCertificate*, SECKEYPrivateKey*, const SSLExtraServerCertData*, unsigned int)' at sslcert.c:662:1 has some indirect sub-type changes:
|
|
+ parameter 4 of type 'const SSLExtraServerCertData*' has sub-type changes:
|
|
+ in pointed to type 'const SSLExtraServerCertData':
|
|
+ in unqualified underlying type 'typedef SSLExtraServerCertData' at sslt.h:310:1:
|
|
+ underlying type 'struct SSLExtraServerCertDataStr' at sslt.h:269:1 changed:
|
|
+ type size hasn't changed
|
|
+ 1 data member change:
|
|
+ type of 'SSLAuthType SSLExtraServerCertDataStr::authType' changed:
|
|
+ underlying type 'enum __anonymous_enum__' at sslt.h:176:1 changed:
|
|
+ type size hasn't changed
|
|
+ 3 enumerator insertions:
|
|
+ '__anonymous_enum__::ssl_auth_mldsa44' value '11'
|
|
+ '__anonymous_enum__::ssl_auth_mldsa65' value '12'
|
|
+ '__anonymous_enum__::ssl_auth_mldsa87' value '13'
|
|
+
|
|
+ 1 enumerator change:
|
|
+ '__anonymous_enum__::ssl_auth_size' from value '11' to '14' at sslt.h:180:1
|
|
+
|
|
+
|
|
+
|
|
+
|
|
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
|
|
--- a/lib/ssl/ssl3con.c
|
|
+++ b/lib/ssl/ssl3con.c
|
|
@@ -69,10 +69,11 @@
|
|
static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
|
|
PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
|
|
PRBool ssl_IsRsaeSignatureScheme(SSLSignatureScheme scheme);
|
|
PRBool ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme);
|
|
PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
|
|
+PRBool ssl_IsMldsaSignatureScheme(SSLSignatureScheme scheme);
|
|
static SECStatus ssl3_UpdateDefaultHandshakeHashes(sslSocket *ss,
|
|
const unsigned char *b,
|
|
unsigned int l);
|
|
const PRUint32 kSSLSigSchemePolicy =
|
|
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_ANY_SIGNATURE;
|
|
@@ -203,11 +204,14 @@
|
|
ssl_sig_rsa_pkcs1_sha512,
|
|
ssl_sig_rsa_pkcs1_sha1,
|
|
ssl_sig_dsa_sha256,
|
|
ssl_sig_dsa_sha384,
|
|
ssl_sig_dsa_sha512,
|
|
- ssl_sig_dsa_sha1
|
|
+ ssl_sig_dsa_sha1,
|
|
+ ssl_sig_mldsa44,
|
|
+ ssl_sig_mldsa65,
|
|
+ ssl_sig_mldsa87,
|
|
};
|
|
PR_STATIC_ASSERT(PR_ARRAY_SIZE(defaultSignatureSchemes) <=
|
|
MAX_SIGNATURE_SCHEMES);
|
|
|
|
/* Verify that SSL_ImplementedCiphers and cipherSuites are in consistent order.
|
|
@@ -361,11 +365,14 @@
|
|
CKM_ECDH1_DERIVE, /* ssl_auth_ecdh_rsa */
|
|
CKM_ECDH1_DERIVE, /* ssl_auth_ecdh_ecdsa */
|
|
CKM_RSA_PKCS, /* ssl_auth_rsa_sign */
|
|
CKM_RSA_PKCS_PSS, /* ssl_auth_rsa_pss */
|
|
CKM_HKDF_DATA, /* ssl_auth_psk (just check for HKDF) */
|
|
- CKM_INVALID_MECHANISM /* ssl_auth_tls13_any */
|
|
+ CKM_INVALID_MECHANISM, /* ssl_auth_tls13_any */
|
|
+ CKM_ML_DSA, /* ssl_auth_mldsa44 */
|
|
+ CKM_ML_DSA, /* ssl_auth_mldsa65 */
|
|
+ CKM_ML_DSA, /* ssl_auth_mldsa87 */
|
|
};
|
|
PR_STATIC_ASSERT(PR_ARRAY_SIZE(auth_alg_defs) == ssl_auth_size);
|
|
|
|
static const CK_MECHANISM_TYPE kea_alg_defs[] = {
|
|
CKM_INVALID_MECHANISM, /* ssl_kea_null */
|
|
@@ -917,10 +924,18 @@
|
|
{
|
|
PRCList *cursor;
|
|
if (authType == ssl_auth_null || authType == ssl_auth_psk || authType == ssl_auth_tls13_any) {
|
|
return PR_TRUE;
|
|
}
|
|
+ /* mldsa is only supported in TLS 1.3 or greater */
|
|
+ if (maxVersion < SSL_LIBRARY_VERSION_TLS_1_3 &&
|
|
+ (authType == ssl_auth_mldsa44 ||
|
|
+ authType == ssl_auth_mldsa65 ||
|
|
+ authType == ssl_auth_mldsa87)) {
|
|
+ return PR_FALSE;
|
|
+ }
|
|
+
|
|
for (cursor = PR_NEXT_LINK(&ss->serverCerts);
|
|
cursor != &ss->serverCerts;
|
|
cursor = PR_NEXT_LINK(cursor)) {
|
|
sslServerCert *cert = (sslServerCert *)cursor;
|
|
if (!cert->serverKeyPair ||
|
|
@@ -989,19 +1004,28 @@
|
|
}
|
|
|
|
/* Check that a signature scheme is accepted.
|
|
* Both by policy and by having a token that supports it. */
|
|
static PRBool
|
|
-ssl_SignatureSchemeAccepted(PRUint16 minVersion,
|
|
+ssl_SignatureSchemeAccepted(PRUint16 maxVersion,
|
|
+ PRUint16 minVersion,
|
|
SSLSignatureScheme scheme,
|
|
PRBool forCert)
|
|
{
|
|
/* Disable RSA-PSS schemes if there are no tokens to verify them. */
|
|
if (ssl_IsRsaPssSignatureScheme(scheme)) {
|
|
if (!PK11_TokenExists(auth_alg_defs[ssl_auth_rsa_pss])) {
|
|
return PR_FALSE;
|
|
}
|
|
+ } else if (ssl_IsMldsaSignatureScheme(scheme)) {
|
|
+ /* ML-DSA: only in TLS 1.3 and later. */
|
|
+ if (maxVersion < SSL_LIBRARY_VERSION_TLS_1_3) {
|
|
+ return PR_FALSE;
|
|
+ }
|
|
+ if (!PK11_TokenExists(auth_alg_defs[ssl_auth_mldsa44])) {
|
|
+ return PR_FALSE;
|
|
+ }
|
|
} else if (!forCert && ssl_IsRsaPkcs1SignatureScheme(scheme)) {
|
|
/* Disable PKCS#1 signatures if we are limited to TLS 1.3.
|
|
* We still need to advertise PKCS#1 signatures in CH and CR
|
|
* for certificate signatures.
|
|
*/
|
|
@@ -1046,11 +1070,11 @@
|
|
}
|
|
}
|
|
|
|
/* Ensure that there is a signature scheme that can be accepted.*/
|
|
for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
|
|
- if (ssl_SignatureSchemeAccepted(ss->vrange.min,
|
|
+ if (ssl_SignatureSchemeAccepted(ss->vrange.max, ss->vrange.min,
|
|
ss->ssl3.signatureSchemes[i],
|
|
PR_FALSE /* forCert */)) {
|
|
return SECSuccess;
|
|
}
|
|
}
|
|
@@ -1077,11 +1101,12 @@
|
|
SSLSignatureScheme scheme = ss->ssl3.signatureSchemes[i];
|
|
SSLAuthType schemeAuthType = ssl_SignatureSchemeToAuthType(scheme);
|
|
PRBool acceptable = authType == schemeAuthType ||
|
|
(schemeAuthType == ssl_auth_rsa_pss &&
|
|
authType == ssl_auth_rsa_sign);
|
|
- if (acceptable && ssl_SignatureSchemeAccepted(ss->version, scheme, PR_FALSE /* forCert */)) {
|
|
+ if (acceptable && ssl_SignatureSchemeAccepted(ss->version, ss->version,
|
|
+ scheme, PR_FALSE /* forCert */)) {
|
|
return PR_TRUE;
|
|
}
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
@@ -3569,10 +3594,11 @@
|
|
case ssl_hash_none:
|
|
/* ssl_hash_none is for pre-1.2 suites, which use SHA-256. */
|
|
return CKM_SHA256;
|
|
case ssl_hash_sha1:
|
|
return CKM_SHA_1;
|
|
+ /* don't return a mechansim for ml_dsa hashes */
|
|
default:
|
|
PORT_Assert(0);
|
|
}
|
|
return CKM_SHA256;
|
|
}
|
|
@@ -4525,10 +4551,16 @@
|
|
return SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
|
|
case ssl_auth_ecdsa:
|
|
return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
|
case ssl_auth_dsa:
|
|
return SEC_OID_ANSIX9_DSA_SIGNATURE;
|
|
+ case ssl_auth_mldsa44:
|
|
+ return SEC_OID_ML_DSA_44;
|
|
+ case ssl_auth_mldsa65:
|
|
+ return SEC_OID_ML_DSA_65;
|
|
+ case ssl_auth_mldsa87:
|
|
+ return SEC_OID_ML_DSA_87;
|
|
default:
|
|
break;
|
|
}
|
|
/* shouldn't ever get there */
|
|
PORT_Assert(0);
|
|
@@ -4561,10 +4593,14 @@
|
|
case ssl_sig_rsa_pss_pss_sha512:
|
|
case ssl_sig_dsa_sha512:
|
|
return ssl_hash_sha512;
|
|
case ssl_sig_rsa_pkcs1_sha1md5:
|
|
return ssl_hash_none; /* Special for TLS 1.0/1.1. */
|
|
+ case ssl_sig_mldsa44:
|
|
+ case ssl_sig_mldsa65:
|
|
+ case ssl_sig_mldsa87:
|
|
+ return ssl_hash_none; /* ml_dsa does no hashing */
|
|
case ssl_sig_none:
|
|
case ssl_sig_ed25519:
|
|
case ssl_sig_ed448:
|
|
break;
|
|
}
|
|
@@ -4613,14 +4649,38 @@
|
|
return PR_FALSE;
|
|
}
|
|
/* With TLS 1.3, EC keys should have been selected based on calling
|
|
* ssl_SignatureSchemeFromSpki(), reject them otherwise. */
|
|
return spkiOid != SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
|
+ } else {
|
|
+ if (ssl_IsMldsaSignatureScheme(scheme)) {
|
|
+ return PR_FALSE;
|
|
+ }
|
|
}
|
|
return PR_TRUE;
|
|
}
|
|
|
|
+/* some schmemes match 1 for 1 to oids, for those schemes, we
|
|
+ * can return the oid directly. If this function return ssl_sig_none,
|
|
+ * it means the oid doesn't match a scheme or matches more than one
|
|
+ * scheme */
|
|
+SSLSignatureScheme
|
|
+ssl_SignatureSchemeFromPublicKeyOid(SECOidTag tag)
|
|
+{
|
|
+ switch (tag) {
|
|
+ case SEC_OID_ML_DSA_44:
|
|
+ return ssl_sig_mldsa44;
|
|
+ case SEC_OID_ML_DSA_65:
|
|
+ return ssl_sig_mldsa65;
|
|
+ case SEC_OID_ML_DSA_87:
|
|
+ return ssl_sig_mldsa87;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return ssl_sig_none;
|
|
+}
|
|
+
|
|
static SECStatus
|
|
ssl_SignatureSchemeFromPssSpki(const CERTSubjectPublicKeyInfo *spki,
|
|
SSLSignatureScheme *scheme)
|
|
{
|
|
SECKEYRSAPSSParams pssParam = { 0 };
|
|
@@ -4709,22 +4769,27 @@
|
|
ssl_SignatureSchemeFromSpki(const CERTSubjectPublicKeyInfo *spki,
|
|
PRBool isTls13, SSLSignatureScheme *scheme)
|
|
{
|
|
SECOidTag spkiOid = SECOID_GetAlgorithmTag(&spki->algorithm);
|
|
|
|
- if (spkiOid == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
|
|
- return ssl_SignatureSchemeFromPssSpki(spki, scheme);
|
|
- }
|
|
-
|
|
- /* Only do this lookup for TLS 1.3, where the scheme can be determined from
|
|
- * the SPKI alone because the ECDSA key size determines the hash. Earlier
|
|
- * TLS versions allow the same EC key to be used with different hashes. */
|
|
- if (isTls13 && spkiOid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
|
|
- return ssl_SignatureSchemeFromEcSpki(spki, scheme);
|
|
- }
|
|
-
|
|
*scheme = ssl_sig_none;
|
|
+ switch (spkiOid) {
|
|
+ case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
|
|
+ return ssl_SignatureSchemeFromPssSpki(spki, scheme);
|
|
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
|
+ /* Only do this lookup for TLS 1.3, where the scheme can be
|
|
+ * determined from the SPKI alone because the ECDSA key size
|
|
+ * determines the hash. Earlier TLS versions allow the same
|
|
+ * EC key to be used with different hashes. */
|
|
+ if (isTls13) {
|
|
+ return ssl_SignatureSchemeFromEcSpki(spki, scheme);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ *scheme = ssl_SignatureSchemeFromPublicKeyOid(spkiOid);
|
|
+ break;
|
|
+ }
|
|
return SECSuccess;
|
|
}
|
|
|
|
/* Check that a signature scheme is enabled by configuration. */
|
|
PRBool
|
|
@@ -4826,10 +4891,13 @@
|
|
case ssl_sig_rsa_pss_pss_sha384:
|
|
case ssl_sig_rsa_pss_pss_sha512:
|
|
case ssl_sig_ecdsa_secp256r1_sha256:
|
|
case ssl_sig_ecdsa_secp384r1_sha384:
|
|
case ssl_sig_ecdsa_secp521r1_sha512:
|
|
+ case ssl_sig_mldsa44:
|
|
+ case ssl_sig_mldsa65:
|
|
+ case ssl_sig_mldsa87:
|
|
case ssl_sig_dsa_sha1:
|
|
case ssl_sig_dsa_sha256:
|
|
case ssl_sig_dsa_sha384:
|
|
case ssl_sig_dsa_sha512:
|
|
case ssl_sig_ecdsa_sha1:
|
|
@@ -4908,10 +4976,25 @@
|
|
return PR_FALSE;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
+PRBool
|
|
+ssl_IsMldsaSignatureScheme(SSLSignatureScheme scheme)
|
|
+{
|
|
+ switch (scheme) {
|
|
+ case ssl_sig_mldsa44:
|
|
+ case ssl_sig_mldsa65:
|
|
+ case ssl_sig_mldsa87:
|
|
+ return PR_TRUE;
|
|
+
|
|
+ default:
|
|
+ return PR_FALSE;
|
|
+ }
|
|
+ return PR_FALSE;
|
|
+}
|
|
+
|
|
SSLAuthType
|
|
ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
|
|
{
|
|
switch (scheme) {
|
|
case ssl_sig_rsa_pkcs1_sha1:
|
|
@@ -4936,10 +5019,21 @@
|
|
case ssl_sig_dsa_sha1:
|
|
case ssl_sig_dsa_sha256:
|
|
case ssl_sig_dsa_sha384:
|
|
case ssl_sig_dsa_sha512:
|
|
return ssl_auth_dsa;
|
|
+ /* while there is one mechanism for ML-DSA,
|
|
+ * server cert selection depends on which
|
|
+ * flavor (paramset) is being used, so
|
|
+ * we need one auth foreach param set.
|
|
+ */
|
|
+ case ssl_sig_mldsa44:
|
|
+ return ssl_auth_mldsa44;
|
|
+ case ssl_sig_mldsa65:
|
|
+ return ssl_auth_mldsa65;
|
|
+ case ssl_sig_mldsa87:
|
|
+ return ssl_auth_mldsa87;
|
|
|
|
default:
|
|
PORT_Assert(0);
|
|
}
|
|
return ssl_auth_null;
|
|
@@ -10490,17 +10584,18 @@
|
|
|
|
return SECFailure;
|
|
}
|
|
|
|
SECStatus
|
|
-ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint16 minVersion, PRBool forCert,
|
|
- PRBool grease, sslBuffer *buf)
|
|
+ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint16 maxVersion, PRUint16 minVersion,
|
|
+ PRBool forCert, PRBool grease, sslBuffer *buf)
|
|
{
|
|
SSLSignatureScheme filtered[MAX_SIGNATURE_SCHEMES] = { 0 };
|
|
unsigned int filteredCount = 0;
|
|
|
|
- SECStatus rv = ssl3_FilterSigAlgs(ss, minVersion, PR_FALSE, forCert,
|
|
+ SECStatus rv = ssl3_FilterSigAlgs(ss, maxVersion, minVersion,
|
|
+ PR_FALSE, forCert,
|
|
PR_ARRAY_SIZE(filtered),
|
|
filtered, &filteredCount);
|
|
if (rv != SECSuccess) {
|
|
return SECFailure;
|
|
}
|
|
@@ -10573,12 +10668,12 @@
|
|
* requires that PKCS#1 schemes are placed last in the list if they
|
|
* are present. This sorting can be removed once we support
|
|
* signature_algorithms_cert.
|
|
*/
|
|
SECStatus
|
|
-ssl3_FilterSigAlgs(const sslSocket *ss, PRUint16 minVersion, PRBool disableRsae,
|
|
- PRBool forCert,
|
|
+ssl3_FilterSigAlgs(const sslSocket *ss, PRUint16 maxVersion, PRUint16 minVersion,
|
|
+ PRBool disableRsae, PRBool forCert,
|
|
unsigned int maxSchemes, SSLSignatureScheme *filteredSchemes,
|
|
unsigned int *numFilteredSchemes)
|
|
{
|
|
PORT_Assert(filteredSchemes);
|
|
PORT_Assert(numFilteredSchemes);
|
|
@@ -10591,25 +10686,25 @@
|
|
PRBool allowUnsortedPkcs1 = forCert && minVersion < SSL_LIBRARY_VERSION_TLS_1_3;
|
|
for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
|
|
if (disableRsae && ssl_IsRsaeSignatureScheme(ss->ssl3.signatureSchemes[i])) {
|
|
continue;
|
|
}
|
|
- if (ssl_SignatureSchemeAccepted(minVersion,
|
|
+ if (ssl_SignatureSchemeAccepted(maxVersion, minVersion,
|
|
ss->ssl3.signatureSchemes[i],
|
|
allowUnsortedPkcs1)) {
|
|
filteredSchemes[(*numFilteredSchemes)++] = ss->ssl3.signatureSchemes[i];
|
|
}
|
|
}
|
|
if (forCert && !allowUnsortedPkcs1) {
|
|
for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
|
|
if (disableRsae && ssl_IsRsaeSignatureScheme(ss->ssl3.signatureSchemes[i])) {
|
|
continue;
|
|
}
|
|
- if (!ssl_SignatureSchemeAccepted(minVersion,
|
|
+ if (!ssl_SignatureSchemeAccepted(maxVersion, minVersion,
|
|
ss->ssl3.signatureSchemes[i],
|
|
PR_FALSE) &&
|
|
- ssl_SignatureSchemeAccepted(minVersion,
|
|
+ ssl_SignatureSchemeAccepted(maxVersion, minVersion,
|
|
ss->ssl3.signatureSchemes[i],
|
|
PR_TRUE)) {
|
|
filteredSchemes[(*numFilteredSchemes)++] = ss->ssl3.signatureSchemes[i];
|
|
}
|
|
}
|
|
@@ -10648,11 +10743,11 @@
|
|
certTypes = certificate_types;
|
|
certTypesLength = sizeof certificate_types;
|
|
|
|
length = 1 + certTypesLength + 2 + calen;
|
|
if (isTLS12) {
|
|
- rv = ssl3_EncodeSigAlgs(ss, ss->version, PR_TRUE /* forCert */,
|
|
+ rv = ssl3_EncodeSigAlgs(ss, ss->version, ss->version, PR_TRUE /* forCert */,
|
|
PR_FALSE /* GREASE */, &sigAlgsBuf);
|
|
if (rv != SECSuccess) {
|
|
return rv;
|
|
}
|
|
length += SSL_BUFFER_LEN(&sigAlgsBuf);
|
|
@@ -11854,10 +11949,15 @@
|
|
/* Don't check EC strength here on the understanding that we
|
|
* only support curves we like. */
|
|
minKey = ss->sec.authKeyBits;
|
|
}
|
|
break;
|
|
+ case mldsaKey:
|
|
+ /* ML DSA has fixed sizes per param set and are handled by
|
|
+ * separate policy oids for each param set */
|
|
+ minKey = ss->sec.authKeyBits;
|
|
+ break;
|
|
|
|
default:
|
|
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
|
|
return SECFailure;
|
|
}
|
|
diff --git a/lib/ssl/ssl3exthandle.c b/lib/ssl/ssl3exthandle.c
|
|
--- a/lib/ssl/ssl3exthandle.c
|
|
+++ b/lib/ssl/ssl3exthandle.c
|
|
@@ -1653,17 +1653,21 @@
|
|
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_2) {
|
|
return SECSuccess;
|
|
}
|
|
|
|
PRUint16 minVersion;
|
|
+ PRUint16 maxVersion;
|
|
if (ss->sec.isServer) {
|
|
+ maxVersion = ss->version; /* CertificateRequest */
|
|
minVersion = ss->version; /* CertificateRequest */
|
|
} else {
|
|
+ maxVersion = ss->vrange.max; /* ClientHello */
|
|
minVersion = ss->vrange.min; /* ClientHello */
|
|
}
|
|
|
|
- SECStatus rv = ssl3_EncodeSigAlgs(ss, minVersion, PR_TRUE /* forCert */,
|
|
+ SECStatus rv = ssl3_EncodeSigAlgs(ss, maxVersion, minVersion,
|
|
+ PR_TRUE /* forCert */,
|
|
ss->opt.enableGrease, buf);
|
|
if (rv != SECSuccess) {
|
|
return SECFailure;
|
|
}
|
|
|
|
diff --git a/lib/ssl/sslcert.c b/lib/ssl/sslcert.c
|
|
--- a/lib/ssl/sslcert.c
|
|
+++ b/lib/ssl/sslcert.c
|
|
@@ -568,10 +568,27 @@
|
|
if (cert->keyUsage & KU_KEY_ENCIPHERMENT) {
|
|
authTypes |= 1 << ssl_GetEcdhAuthType(cert);
|
|
}
|
|
break;
|
|
|
|
+ case SEC_OID_ML_DSA_44:
|
|
+ if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
|
+ authTypes |= 1 << ssl_auth_mldsa44;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case SEC_OID_ML_DSA_65:
|
|
+ if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
|
+ authTypes |= 1 << ssl_auth_mldsa65;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case SEC_OID_ML_DSA_87:
|
|
+ if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
|
+ authTypes |= 1 << ssl_auth_mldsa87;
|
|
+ }
|
|
+
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Check that we successfully picked an authType */
|
|
@@ -729,10 +746,19 @@
|
|
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
|
mask |= 1 << ssl_auth_ecdsa;
|
|
mask |= 1 << ssl_auth_ecdh_rsa;
|
|
mask |= 1 << ssl_auth_ecdh_ecdsa;
|
|
break;
|
|
+ case SEC_OID_ML_DSA_44:
|
|
+ mask |= 1 << ssl_auth_mldsa44;
|
|
+ break;
|
|
+ case SEC_OID_ML_DSA_65:
|
|
+ mask |= 1 << ssl_auth_mldsa65;
|
|
+ break;
|
|
+ case SEC_OID_ML_DSA_87:
|
|
+ mask |= 1 << ssl_auth_mldsa87;
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
PORT_Assert(authTypes);
|
|
/* Simply test that no inappropriate auth types are set. */
|
|
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
|
|
--- a/lib/ssl/sslimpl.h
|
|
+++ b/lib/ssl/sslimpl.h
|
|
@@ -1746,16 +1746,18 @@
|
|
SECStatus ssl_SetAuthKeyBits(sslSocket *ss, const SECKEYPublicKey *pubKey);
|
|
SECStatus ssl3_HandleServerSpki(sslSocket *ss);
|
|
SECStatus ssl3_AuthCertificate(sslSocket *ss);
|
|
SECStatus ssl_ReadCertificateStatus(sslSocket *ss, PRUint8 *b,
|
|
PRUint32 length);
|
|
-SECStatus ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint16 minVersion, PRBool forCert,
|
|
+SECStatus ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint16 maxVersion,
|
|
+ PRUint16 minVersion, PRBool forCert,
|
|
PRBool grease, sslBuffer *buf);
|
|
SECStatus ssl3_EncodeFilteredSigAlgs(const sslSocket *ss,
|
|
const SSLSignatureScheme *schemes,
|
|
PRUint32 numSchemes, PRBool grease, sslBuffer *buf);
|
|
-SECStatus ssl3_FilterSigAlgs(const sslSocket *ss, PRUint16 minVersion, PRBool disableRsae, PRBool forCert,
|
|
+SECStatus ssl3_FilterSigAlgs(const sslSocket *ss, PRUint16 maxVersion, PRUint16 minVersion,
|
|
+ PRBool disableRsae, PRBool forCert,
|
|
unsigned int maxSchemes, SSLSignatureScheme *filteredSchemes,
|
|
unsigned int *numFilteredSchemes);
|
|
SECStatus ssl_GetCertificateRequestCAs(const sslSocket *ss,
|
|
unsigned int *calenp,
|
|
const SECItem **namesp,
|
|
@@ -1821,10 +1823,11 @@
|
|
SECStatus ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec,
|
|
SSLContentType contentType, sslBuffer *wrBuf,
|
|
PRBool *needsLength);
|
|
PRBool ssl_SignatureSchemeValid(SSLSignatureScheme scheme, SECOidTag spkiOid,
|
|
PRBool isTls13);
|
|
+SSLSignatureScheme ssl_SignatureSchemeFromPublicKeyOid(SECOidTag tag);
|
|
|
|
/* Pull in DTLS functions */
|
|
#include "dtlscon.h"
|
|
|
|
/* Pull in TLS 1.3 functions */
|
|
diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
|
|
--- a/lib/ssl/sslt.h
|
|
+++ b/lib/ssl/sslt.h
|
|
@@ -154,10 +154,14 @@
|
|
ssl_sig_dsa_sha256 = 0x0402,
|
|
ssl_sig_dsa_sha384 = 0x0502,
|
|
ssl_sig_dsa_sha512 = 0x0602,
|
|
ssl_sig_ecdsa_sha1 = 0x0203,
|
|
|
|
+ ssl_sig_mldsa44 = 0x0904,
|
|
+ ssl_sig_mldsa65 = 0x0905,
|
|
+ ssl_sig_mldsa87 = 0x0906,
|
|
+
|
|
/* The following value (which can't be used in the protocol), represents
|
|
* the RSA signature using SHA-1 and MD5 that is used in TLS 1.0 and 1.1.
|
|
* This is reported as a signature scheme when TLS 1.0 or 1.1 is used.
|
|
* This should not be passed to SSL_SignatureSchemePrefSet(); this
|
|
* signature scheme is always used and cannot be disabled. */
|
|
@@ -183,10 +187,13 @@
|
|
ssl_auth_ecdh_ecdsa = 6, /* ECDH cert with an ECDSA signature. */
|
|
ssl_auth_rsa_sign = 7, /* RSA signing with an rsaEncryption key. */
|
|
ssl_auth_rsa_pss = 8, /* RSA signing with a PSS key. */
|
|
ssl_auth_psk = 9,
|
|
ssl_auth_tls13_any = 10,
|
|
+ ssl_auth_mldsa44 = 11, /* use separate auth for each paramset */
|
|
+ ssl_auth_mldsa65 = 12, /* so we can properly identify the certs */
|
|
+ ssl_auth_mldsa87 = 13,
|
|
ssl_auth_size /* number of authentication types */
|
|
} SSLAuthType;
|
|
|
|
typedef enum {
|
|
ssl_psk_none = 0,
|
|
diff --git a/lib/ssl/tls13exthandle.c b/lib/ssl/tls13exthandle.c
|
|
--- a/lib/ssl/tls13exthandle.c
|
|
+++ b/lib/ssl/tls13exthandle.c
|
|
@@ -1450,11 +1450,11 @@
|
|
* the "advertised" list, then encode them to be sent. If we receive
|
|
* a DC in response, validate that it matches one of the advertised
|
|
* schemes. */
|
|
SSLSignatureScheme filtered[MAX_SIGNATURE_SCHEMES] = { 0 };
|
|
unsigned int filteredCount = 0;
|
|
- SECStatus rv = ssl3_FilterSigAlgs(ss, ss->vrange.max,
|
|
+ SECStatus rv = ssl3_FilterSigAlgs(ss, ss->vrange.max, ss->vrange.max,
|
|
PR_TRUE /* disableRsae */,
|
|
PR_FALSE /* forCert */,
|
|
MAX_SIGNATURE_SCHEMES,
|
|
filtered,
|
|
&filteredCount);
|
|
diff --git a/lib/ssl/tls13signature.c b/lib/ssl/tls13signature.c
|
|
--- a/lib/ssl/tls13signature.c
|
|
+++ b/lib/ssl/tls13signature.c
|
|
@@ -55,10 +55,24 @@
|
|
break;
|
|
case ssl_sig_ecdsa_secp521r1_sha512:
|
|
algTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
|
|
hashAlgTag = SEC_OID_SHA512;
|
|
break;
|
|
+ /* ML-DSA fully defines the hash and sign algorithm,
|
|
+ * we set the hash alg to the same as the sign alg. */
|
|
+ case ssl_sig_mldsa44:
|
|
+ algTag = SEC_OID_ML_DSA_44;
|
|
+ hashAlgTag = SEC_OID_ML_DSA_44;
|
|
+ break;
|
|
+ case ssl_sig_mldsa65:
|
|
+ algTag = SEC_OID_ML_DSA_65;
|
|
+ hashAlgTag = SEC_OID_ML_DSA_65;
|
|
+ break;
|
|
+ case ssl_sig_mldsa87:
|
|
+ algTag = SEC_OID_ML_DSA_87;
|
|
+ hashAlgTag = SEC_OID_ML_DSA_87;
|
|
+ break;
|
|
|
|
/* the following is unsupported in tls 1.3 and greater, just break.
|
|
* We include them here explicitly so we get the compiler warning about
|
|
* missing enums in the switch statement. default would be a break anyway.
|
|
* That way we'll know to update this table when new algorithms are
|
|
diff --git a/lib/ssl/tls13subcerts.c b/lib/ssl/tls13subcerts.c
|
|
--- a/lib/ssl/tls13subcerts.c
|
|
+++ b/lib/ssl/tls13subcerts.c
|
|
@@ -649,11 +649,17 @@
|
|
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
|
return NULL;
|
|
}
|
|
return SECKEY_CreateSubjectPublicKeyInfo(dcPub);
|
|
}
|
|
-
|
|
+ case mldsaKey:
|
|
+ if (ssl_SignatureSchemeFromPublicKeyOid(dcPub->u.mldsa.paramSet)
|
|
+ != dcCertVerifyAlg) {
|
|
+ PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
|
+ return NULL;
|
|
+ }
|
|
+ return SECKEY_CreateSubjectPublicKeyInfo(dcPub);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_KEY);
|
|
|