diff options
Diffstat (limited to 'security/nss/lib/ssl/sslcert.c')
-rw-r--r-- | security/nss/lib/ssl/sslcert.c | 109 |
1 files changed, 103 insertions, 6 deletions
diff --git a/security/nss/lib/ssl/sslcert.c b/security/nss/lib/ssl/sslcert.c index 878df761e..d2c9480d5 100644 --- a/security/nss/lib/ssl/sslcert.c +++ b/security/nss/lib/ssl/sslcert.c @@ -8,10 +8,11 @@ #include "ssl.h" #include "sslimpl.h" -#include "secoid.h" /* for SECOID_GetAlgorithmTag */ -#include "pk11func.h" /* for PK11_ReferenceSlot */ -#include "nss.h" /* for NSS_RegisterShutdown */ -#include "prinit.h" /* for PR_CallOnceWithArg */ +#include "secoid.h" /* for SECOID_GetAlgorithmTag */ +#include "pk11func.h" /* for PK11_ReferenceSlot */ +#include "nss.h" /* for NSS_RegisterShutdown */ +#include "prinit.h" /* for PR_CallOnceWithArg */ +#include "tls13subcerts.h" /* for tls13_ReadDelegatedCredential */ /* This global item is used only in servers. It is is initialized by * SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest(). @@ -102,6 +103,8 @@ ssl_NewServerCert() sc->serverCertChain = NULL; sc->certStatusArray = NULL; sc->signedCertTimestamps.len = 0; + sc->delegCred.len = 0; + sc->delegCredKeyPair = NULL; return sc; } @@ -148,8 +151,17 @@ ssl_CopyServerCert(const sslServerCert *oc) } if (SECITEM_CopyItem(NULL, &sc->signedCertTimestamps, - &oc->signedCertTimestamps) != SECSuccess) + &oc->signedCertTimestamps) != SECSuccess) { goto loser; + } + + if (SECITEM_CopyItem(NULL, &sc->delegCred, &oc->delegCred) != SECSuccess) { + goto loser; + } + if (oc->delegCredKeyPair) { + sc->delegCredKeyPair = ssl_GetKeyPairRef(oc->delegCredKeyPair); + } + return sc; loser: ssl_FreeServerCert(sc); @@ -178,6 +190,12 @@ ssl_FreeServerCert(sslServerCert *sc) if (sc->signedCertTimestamps.len) { SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE); } + if (sc->delegCred.len) { + SECITEM_FreeItem(&sc->delegCred, PR_FALSE); + } + if (sc->delegCredKeyPair) { + ssl_FreeKeyPair(sc->delegCredKeyPair); + } PORT_ZFree(sc, sizeof(*sc)); } @@ -309,6 +327,79 @@ ssl_PopulateSignedCertTimestamps(sslServerCert *sc, return SECSuccess; } +/* Installs the given delegated credential (DC) and DC private key into the + * certificate. + * + * It's the caller's responsibility to ensure that the DC is well-formed and + * that the DC public key matches the DC private key. + */ +static SECStatus +ssl_PopulateDelegatedCredential(sslServerCert *sc, + const SECItem *delegCred, + const SECKEYPrivateKey *delegCredPrivKey) +{ + sslDelegatedCredential *dc = NULL; + + if (sc->delegCred.len) { + SECITEM_FreeItem(&sc->delegCred, PR_FALSE); + } + + if (sc->delegCredKeyPair) { + ssl_FreeKeyPair(sc->delegCredKeyPair); + sc->delegCredKeyPair = NULL; + } + + /* Both the DC and its private are present. */ + if (delegCred && delegCredPrivKey) { + SECStatus rv; + SECKEYPublicKey *pub; + SECKEYPrivateKey *priv; + + if (!delegCred->data || delegCred->len == 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; + } + + /* Parse the DC. */ + rv = tls13_ReadDelegatedCredential(delegCred->data, delegCred->len, &dc); + if (rv != SECSuccess) { + goto loser; + } + + /* Make a copy of the DC. */ + rv = SECITEM_CopyItem(NULL, &sc->delegCred, delegCred); + if (rv != SECSuccess) { + goto loser; + } + + /* Make a copy of the DC private key. */ + priv = SECKEY_CopyPrivateKey(delegCredPrivKey); + if (!priv) { + goto loser; + } + + /* parse public key from the DC. */ + pub = SECKEY_ExtractPublicKey(dc->spki); + if (!pub) { + goto loser; + } + + sc->delegCredKeyPair = ssl_NewKeyPair(priv, pub); + + /* Attempting to configure either the DC or DC private key, but not both. */ + } else if (delegCred || delegCredPrivKey) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; + } + + tls13_DestroyDelegatedCredential(dc); + return SECSuccess; + +loser: + tls13_DestroyDelegatedCredential(dc); + return SECFailure; +} + /* Find any existing certificates that overlap with the new certificate and * either remove any supported authentication types that overlap with the new * certificate or - if they have no types left - remove them entirely. */ @@ -379,6 +470,12 @@ ssl_ConfigCert(sslSocket *ss, sslAuthTypeMask authTypes, if (rv != SECSuccess) { goto loser; } + rv = ssl_PopulateDelegatedCredential(sc, data->delegCred, + data->delegCredPrivKey); + if (rv != SECSuccess) { + error_code = PORT_GetError(); + goto loser; + } ssl_ClearMatchingCerts(ss, sc->authTypes, sc->namedCurve); PR_APPEND_LINK(&sc->link, &ss->serverCerts); return SECSuccess; @@ -548,7 +645,7 @@ SSL_ConfigServerCert(PRFileDesc *fd, CERTCertificate *cert, sslKeyPair *keyPair; SECStatus rv; SSLExtraServerCertData dataCopy = { - ssl_auth_null, NULL, NULL, NULL + ssl_auth_null, NULL, NULL, NULL, NULL, NULL }; sslAuthTypeMask authTypes; |