summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/tls13subcerts.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/tls13subcerts.c')
-rw-r--r--security/nss/lib/ssl/tls13subcerts.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/security/nss/lib/ssl/tls13subcerts.c b/security/nss/lib/ssl/tls13subcerts.c
index 8ae5447f7..6f164c302 100644
--- a/security/nss/lib/ssl/tls13subcerts.c
+++ b/security/nss/lib/ssl/tls13subcerts.c
@@ -7,6 +7,7 @@
#include "nss.h"
#include "pk11func.h"
#include "secder.h"
+#include "sechash.h"
#include "ssl.h"
#include "sslproto.h"
#include "sslimpl.h"
@@ -148,9 +149,7 @@ tls13_GetExpectedCertVerifyAlg(SECItem in, SSLSignatureScheme *certVerifyAlg)
PRBool
tls13_IsVerifyingWithDelegatedCredential(const sslSocket *ss)
{
- /* As of draft-ietf-subcerts-03, only the server may authenticate itself
- * with a DC.
- */
+ /* We currently do not support client-delegated credentials. */
if (ss->sec.isServer ||
!ss->opt.enableDelegatedCredentials ||
!ss->xtnData.peerDelegCred) {
@@ -191,20 +190,21 @@ tls13_MaybeSetDelegatedCredential(sslSocket *ss)
SECKEYPrivateKey *priv;
SSLSignatureScheme scheme;
- /* Assert that the host is the server (as of draft-ietf-subcerts-03, only
- * the server may authenticate itself with a DC), the certificate has been
+ /* Assert that the host is the server (we do not currently support
+ * client-delegated credentials), the certificate has been
* chosen, TLS 1.3 or higher has been negotiated, and that the set of
* signature schemes supported by the client is known.
*/
PORT_Assert(ss->sec.isServer);
PORT_Assert(ss->sec.serverCert);
PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
- PORT_Assert(ss->xtnData.sigSchemes);
+ PORT_Assert(ss->xtnData.peerRequestedDelegCred == !!ss->xtnData.delegCredSigSchemes);
/* Check that the peer has indicated support and that a DC has been
* configured for the selected certificate.
*/
if (!ss->xtnData.peerRequestedDelegCred ||
+ !ss->xtnData.delegCredSigSchemes ||
!ss->sec.serverCert->delegCred.len ||
!ss->sec.serverCert->delegCredKeyPair) {
return SECSuccess;
@@ -227,8 +227,8 @@ tls13_MaybeSetDelegatedCredential(sslSocket *ss)
if (!ssl_SignatureSchemeEnabled(ss, scheme) ||
!ssl_CanUseSignatureScheme(scheme,
- ss->xtnData.sigSchemes,
- ss->xtnData.numSigSchemes,
+ ss->xtnData.delegCredSigSchemes,
+ ss->xtnData.numDelegCredSigSchemes,
PR_FALSE /* requireSha1 */,
doesRsaPss)) {
return SECSuccess;
@@ -379,6 +379,12 @@ tls13_VerifyCredentialSignature(sslSocket *ss, sslDelegatedCredential *dc)
goto loser;
}
+ SECOidTag spkiAlg = SECOID_GetAlgorithmTag(&(dc->spki->algorithm));
+ if (spkiAlg == SEC_OID_PKCS1_RSA_ENCRYPTION) {
+ FATAL_ERROR(ss, SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, illegal_parameter);
+ goto loser;
+ }
+
SECKEY_DestroyPublicKey(pubKey);
sslBuffer_Clear(&dcBuf);
return SECSuccess;
@@ -434,8 +440,10 @@ static SECStatus
tls13_CheckCredentialExpiration(sslSocket *ss, sslDelegatedCredential *dc)
{
SECStatus rv;
- PRTime start, end /* microseconds */;
CERTCertificate *cert = ss->sec.peerCert;
+ /* 7 days in microseconds */
+ static const PRTime kMaxDcValidity = ((PRTime)7 * 24 * 60 * 60 * PR_USEC_PER_SEC);
+ PRTime start, now, end; /* microseconds */
rv = DER_DecodeTimeChoice(&start, &cert->validity.notBefore);
if (rv != SECSuccess) {
@@ -444,11 +452,18 @@ tls13_CheckCredentialExpiration(sslSocket *ss, sslDelegatedCredential *dc)
}
end = start + ((PRTime)dc->validTime * PR_USEC_PER_SEC);
- if (ssl_Time(ss) > end) {
+ now = ssl_Time(ss);
+ if (now > end || end < 0) {
FATAL_ERROR(ss, SSL_ERROR_DC_EXPIRED, illegal_parameter);
return SECFailure;
}
+ /* Not more than 7 days remaining in the validity period. */
+ if (end - now > kMaxDcValidity) {
+ FATAL_ERROR(ss, SSL_ERROR_DC_INAPPROPRIATE_VALIDITY_PERIOD, illegal_parameter);
+ return SECFailure;
+ }
+
return SECSuccess;
}
@@ -456,7 +471,8 @@ tls13_CheckCredentialExpiration(sslSocket *ss, sslDelegatedCredential *dc)
* returns SECFailure. A valid DC meets three requirements: (1) the signature
* was produced by the peer's end-entity certificate, (2) the end-entity
* certificate must have the correct key usage, and (3) the DC must not be
- * expired.
+ * expired and its remaining TTL must be <= the maximum validity period (fixed
+ * as 7 days).
*
* This function calls FATAL_ERROR() when an error occurs.
*/
@@ -538,6 +554,15 @@ tls13_MakePssSpki(const SECKEYPublicKey *pub, SECOidTag hashOid)
goto loser; /* Code already set. */
}
+ /* Always include saltLength: all hashes are larger than 20. */
+ unsigned int saltLength = HASH_ResultLenByOidTag(hashOid);
+ PORT_Assert(saltLength > 20);
+ if (!SEC_ASN1EncodeInteger(arena, &params.saltLength, saltLength)) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ goto loser;
+ }
+ /* Omit the trailerField always. */
+
SECItem *algorithmItem =
SEC_ASN1EncodeItem(arena, NULL, &params,
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate));
@@ -551,8 +576,6 @@ tls13_MakePssSpki(const SECKEYPublicKey *pub, SECOidTag hashOid)
goto loser; /* Code already set. */
}
- PORT_Assert(pub->u.rsa.modulus.type == siUnsignedInteger);
- PORT_Assert(pub->u.rsa.publicExponent.type == siUnsignedInteger);
SECItem *pubItem = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, pub,
SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate));
if (!pubItem) {
@@ -574,15 +597,13 @@ tls13_MakeDcSpki(const SECKEYPublicKey *dcPub, SSLSignatureScheme dcCertVerifyAl
case rsaKey: {
SECOidTag hashOid;
switch (dcCertVerifyAlg) {
- /* Though we might prefer to use a pure PSS SPKI here, we can't
- * because we have to choose based on client preferences. And
- * not all clients advertise the pss_pss schemes. So use the
- * default SPKI construction for an RSAE SPKI. */
+ /* Note: RSAE schemes are NOT permitted within DC SPKIs. However,
+ * support for their issuance remains so as to enable negative
+ * testing of client behavior. */
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
return SECKEY_CreateSubjectPublicKeyInfo(dcPub);
-
case ssl_sig_rsa_pss_pss_sha256:
hashOid = SEC_OID_SHA256;
break;
@@ -707,7 +728,10 @@ SSLExp_DelegateCredential(const CERTCertificate *cert,
if (dc->alg == ssl_sig_none) {
SECOidTag spkiOid = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
/* If the Cert SPKI contained an AlgorithmIdentifier of "rsaEncryption", set a
- * default rsa_pss_rsae_sha256 scheme. */
+ * default rsa_pss_rsae_sha256 scheme. NOTE: RSAE SPKIs are not permitted within
+ * "real" Delegated Credentials. However, since this function is primarily used for
+ * testing, we retain this support in order to verify that these DCs are rejected
+ * by tls13_VerifyDelegatedCredential. */
if (spkiOid == SEC_OID_PKCS1_RSA_ENCRYPTION) {
SSLSignatureScheme scheme = ssl_sig_rsa_pss_rsae_sha256;
if (ssl_SignatureSchemeValid(scheme, spkiOid, PR_TRUE /* isTls13 */)) {
@@ -752,6 +776,8 @@ SSLExp_DelegateCredential(const CERTCertificate *cert,
goto loser;
}
+ PRINT_BUF(20, (NULL, "delegated credential", dcBuf.buf, dcBuf.len));
+
SECKEY_DestroySubjectPublicKeyInfo(spki);
SECKEY_DestroyPrivateKey(tmpPriv);
tls13_DestroyDelegatedCredential(dc);