2016-04-27 15:51:59 +03:00
|
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* SSL server certificate configuration functions.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#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 */
|
|
|
|
|
|
|
|
static const PRCallOnceType pristineCallOnce;
|
|
|
|
static PRCallOnceType setupServerCAListOnce;
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
serverCAListShutdown(void *appData, void *nssData)
|
|
|
|
{
|
|
|
|
PORT_Assert(ssl3_server_ca_list);
|
|
|
|
if (ssl3_server_ca_list) {
|
|
|
|
CERT_FreeDistNames(ssl3_server_ca_list);
|
|
|
|
ssl3_server_ca_list = NULL;
|
|
|
|
}
|
|
|
|
setupServerCAListOnce = pristineCallOnce;
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PRStatus
|
|
|
|
serverCAListSetup(void *arg)
|
|
|
|
{
|
|
|
|
CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg;
|
|
|
|
SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL);
|
|
|
|
PORT_Assert(SECSuccess == rv);
|
|
|
|
if (SECSuccess == rv) {
|
|
|
|
ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle);
|
|
|
|
return PR_SUCCESS;
|
|
|
|
}
|
|
|
|
return PR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sslServerCert *
|
|
|
|
ssl_NewServerCert(const sslServerCertType *certType)
|
|
|
|
{
|
|
|
|
sslServerCert *sc = PORT_ZNew(sslServerCert);
|
|
|
|
if (!sc) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memcpy(&sc->certType, certType, sizeof(sc->certType));
|
|
|
|
sc->serverCert = NULL;
|
|
|
|
sc->serverCertChain = NULL;
|
|
|
|
sc->certStatusArray = NULL;
|
|
|
|
sc->signedCertTimestamps.len = 0;
|
|
|
|
return sc;
|
|
|
|
}
|
|
|
|
|
2016-06-02 23:33:04 +03:00
|
|
|
sslServerCert *
|
|
|
|
ssl_CopyServerCert(const sslServerCert *oc)
|
|
|
|
{
|
|
|
|
sslServerCert *sc;
|
|
|
|
|
|
|
|
sc = ssl_NewServerCert(&oc->certType);
|
|
|
|
if (!sc) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oc->serverCert && oc->serverCertChain) {
|
|
|
|
sc->serverCert = CERT_DupCertificate(oc->serverCert);
|
|
|
|
if (!sc->serverCert)
|
|
|
|
goto loser;
|
|
|
|
sc->serverCertChain = CERT_DupCertList(oc->serverCertChain);
|
|
|
|
if (!sc->serverCertChain)
|
|
|
|
goto loser;
|
|
|
|
} else {
|
|
|
|
sc->serverCert = NULL;
|
|
|
|
sc->serverCertChain = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oc->serverKeyPair) {
|
|
|
|
sc->serverKeyPair = ssl3_GetKeyPairRef(oc->serverKeyPair);
|
|
|
|
if (!sc->serverKeyPair)
|
|
|
|
goto loser;
|
|
|
|
} else {
|
|
|
|
sc->serverKeyPair = NULL;
|
|
|
|
}
|
|
|
|
sc->serverKeyBits = oc->serverKeyBits;
|
|
|
|
|
|
|
|
if (oc->certStatusArray) {
|
|
|
|
sc->certStatusArray = SECITEM_DupArray(NULL, oc->certStatusArray);
|
|
|
|
if (!sc->certStatusArray)
|
|
|
|
goto loser;
|
|
|
|
} else {
|
|
|
|
sc->certStatusArray = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SECITEM_CopyItem(NULL, &sc->signedCertTimestamps,
|
|
|
|
&oc->signedCertTimestamps) != SECSuccess)
|
|
|
|
goto loser;
|
|
|
|
return sc;
|
|
|
|
loser:
|
|
|
|
ssl_FreeServerCert(sc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-04-27 15:51:59 +03:00
|
|
|
void
|
|
|
|
ssl_FreeServerCert(sslServerCert *sc)
|
|
|
|
{
|
|
|
|
if (!sc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sc->serverCert) {
|
|
|
|
CERT_DestroyCertificate(sc->serverCert);
|
|
|
|
}
|
|
|
|
if (sc->serverCertChain) {
|
|
|
|
CERT_DestroyCertificateList(sc->serverCertChain);
|
|
|
|
}
|
|
|
|
if (sc->serverKeyPair) {
|
|
|
|
ssl3_FreeKeyPair(sc->serverKeyPair);
|
|
|
|
}
|
|
|
|
if (sc->certStatusArray) {
|
|
|
|
SECITEM_FreeArray(sc->certStatusArray, PR_TRUE);
|
|
|
|
}
|
|
|
|
if (sc->signedCertTimestamps.len) {
|
|
|
|
SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE);
|
|
|
|
}
|
|
|
|
PORT_ZFree(sc, sizeof(*sc));
|
|
|
|
}
|
|
|
|
|
|
|
|
sslServerCert *
|
|
|
|
ssl_FindServerCert(const sslSocket *ss,
|
|
|
|
const sslServerCertType *certType)
|
|
|
|
{
|
|
|
|
PRCList *cursor;
|
|
|
|
|
|
|
|
for (cursor = PR_NEXT_LINK(&ss->serverCerts);
|
|
|
|
cursor != &ss->serverCerts;
|
|
|
|
cursor = PR_NEXT_LINK(cursor)) {
|
|
|
|
sslServerCert *cert = (sslServerCert *)cursor;
|
|
|
|
if (cert->certType.authType != certType->authType) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch (cert->certType.authType) {
|
|
|
|
case ssl_auth_ecdsa:
|
|
|
|
case ssl_auth_ecdh_rsa:
|
|
|
|
case ssl_auth_ecdh_ecdsa:
|
|
|
|
/* Note: For deprecated APIs, we need to be able to find and
|
|
|
|
match a slot with any named curve or sign type. */
|
|
|
|
if (certType->u.namedCurve != ec_noName &&
|
|
|
|
cert->certType.u.namedCurve != certType->u.namedCurve) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return cert;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
sslServerCert *
|
|
|
|
ssl_FindServerCertByAuthType(const sslSocket *ss, SSLAuthType authType)
|
|
|
|
{
|
|
|
|
sslServerCertType certType;
|
|
|
|
certType.authType = authType;
|
|
|
|
switch (authType) {
|
|
|
|
/* Setting the named curve to ec_noName ensures that all EC certificates
|
|
|
|
* are matched when searching for this slot. */
|
|
|
|
case ssl_auth_ecdsa:
|
|
|
|
case ssl_auth_ecdh_rsa:
|
|
|
|
case ssl_auth_ecdh_ecdsa:
|
|
|
|
certType.u.namedCurve = ec_noName;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ssl_FindServerCert(ss, &certType);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECStatus
|
|
|
|
ssl_OneTimeCertSetup(sslSocket *ss, const sslServerCert *sc)
|
|
|
|
{
|
|
|
|
/* Generate a step-down RSA key. */
|
|
|
|
if (sc->certType.authType == ssl_auth_rsa_decrypt &&
|
|
|
|
sc->serverKeyBits > 512 &&
|
|
|
|
!ss->opt.noStepDown && !ss->stepDownKeyPair) {
|
|
|
|
if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* DH parameters are only needed for DHE_RSA_* and DHE_DSS_* suites. Make
|
|
|
|
* sure that they are properly setup here. */
|
|
|
|
if (sc->certType.authType == ssl_auth_rsa_sign ||
|
|
|
|
sc->certType.authType == ssl_auth_rsa_decrypt ||
|
|
|
|
sc->certType.authType == ssl_auth_dsa) {
|
|
|
|
if (ssl3_SelectDHParams(ss) != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PR_SUCCESS != PR_CallOnceWithArg(&setupServerCAListOnce,
|
|
|
|
&serverCAListSetup,
|
|
|
|
(void *)(ss->dbHandle))) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine which slot a certificate fits into. SSLAuthType is known, but
|
|
|
|
* extra information needs to be worked out from the cert and key. */
|
|
|
|
static void
|
|
|
|
ssl_PopulateCertType(sslServerCertType *certType, SSLAuthType authType,
|
|
|
|
CERTCertificate *cert, ssl3KeyPair *keyPair)
|
|
|
|
{
|
|
|
|
certType->authType = authType;
|
|
|
|
switch (authType) {
|
|
|
|
case ssl_auth_ecdsa:
|
|
|
|
case ssl_auth_ecdh_rsa:
|
|
|
|
case ssl_auth_ecdh_ecdsa:
|
|
|
|
certType->u.namedCurve = ssl3_PubKey2ECName(keyPair->pubKey);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_PopulateServerCert(sslServerCert *sc, CERTCertificate *cert,
|
|
|
|
const CERTCertificateList *certChain)
|
|
|
|
{
|
|
|
|
if (sc->serverCert) {
|
|
|
|
CERT_DestroyCertificate(sc->serverCert);
|
|
|
|
}
|
|
|
|
if (sc->serverCertChain) {
|
|
|
|
CERT_DestroyCertificateList(sc->serverCertChain);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cert) {
|
|
|
|
sc->serverCert = NULL;
|
|
|
|
sc->serverCertChain = NULL;
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->serverCert = CERT_DupCertificate(cert);
|
|
|
|
if (certChain) {
|
|
|
|
sc->serverCertChain = CERT_DupCertList(certChain);
|
|
|
|
} else {
|
|
|
|
sc->serverCertChain =
|
|
|
|
CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer,
|
|
|
|
PR_TRUE);
|
|
|
|
}
|
|
|
|
return sc->serverCertChain ? SECSuccess : SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_PopulateKeyPair(sslServerCert *sc, ssl3KeyPair *keyPair)
|
|
|
|
{
|
|
|
|
/* Copy over the key pair. */
|
|
|
|
if (sc->serverKeyPair) {
|
|
|
|
ssl3_FreeKeyPair(sc->serverKeyPair);
|
|
|
|
}
|
|
|
|
if (keyPair) {
|
|
|
|
/* Get the size of the cert's public key, and remember it. */
|
|
|
|
sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey);
|
|
|
|
if (sc->serverKeyBits == 0) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
SECKEY_CacheStaticFlags(keyPair->privKey);
|
|
|
|
sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair);
|
|
|
|
} else {
|
|
|
|
sc->serverKeyPair = NULL;
|
|
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_PopulateOCSPResponses(sslServerCert *sc,
|
|
|
|
const SECItemArray *stapledOCSPResponses)
|
|
|
|
{
|
|
|
|
if (sc->certStatusArray) {
|
|
|
|
SECITEM_FreeArray(sc->certStatusArray, PR_TRUE);
|
|
|
|
}
|
|
|
|
if (stapledOCSPResponses) {
|
|
|
|
sc->certStatusArray = SECITEM_DupArray(NULL, stapledOCSPResponses);
|
|
|
|
return sc->certStatusArray ? SECSuccess : SECFailure;
|
|
|
|
} else {
|
|
|
|
sc->certStatusArray = NULL;
|
|
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_PopulateSignedCertTimestamps(sslServerCert *sc,
|
|
|
|
const SECItem *signedCertTimestamps)
|
|
|
|
{
|
|
|
|
if (sc->signedCertTimestamps.len) {
|
|
|
|
SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE);
|
|
|
|
}
|
|
|
|
if (signedCertTimestamps) {
|
|
|
|
return SECITEM_CopyItem(NULL, &sc->signedCertTimestamps,
|
|
|
|
signedCertTimestamps);
|
|
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_ConfigCert(sslSocket *ss, CERTCertificate *cert,
|
|
|
|
ssl3KeyPair *keyPair, const SSLExtraServerCertData *data)
|
|
|
|
{
|
|
|
|
sslServerCert *oldsc;
|
|
|
|
sslServerCertType certType;
|
|
|
|
SECStatus rv;
|
|
|
|
sslServerCert *sc = NULL;
|
|
|
|
int error_code = SEC_ERROR_NO_MEMORY;
|
|
|
|
|
|
|
|
PORT_Assert(cert);
|
|
|
|
PORT_Assert(keyPair);
|
|
|
|
PORT_Assert(data);
|
|
|
|
PORT_Assert(data->authType != ssl_auth_null);
|
|
|
|
|
|
|
|
if (!cert || !keyPair || !data || data->authType == ssl_auth_null) {
|
|
|
|
error_code = SEC_ERROR_INVALID_ARGS;
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssl_PopulateCertType(&certType, data->authType, cert, keyPair);
|
|
|
|
|
|
|
|
/* Delete any existing certificate that matches this one, since we can only
|
|
|
|
* use one certificate of a given type. */
|
|
|
|
oldsc = ssl_FindServerCert(ss, &certType);
|
|
|
|
if (oldsc) {
|
|
|
|
PR_REMOVE_LINK(&oldsc->link);
|
|
|
|
ssl_FreeServerCert(oldsc);
|
|
|
|
}
|
|
|
|
sc = ssl_NewServerCert(&certType);
|
|
|
|
if (!sc) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = ssl_PopulateServerCert(sc, cert, data->certChain);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
rv = ssl_PopulateKeyPair(sc, keyPair);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
error_code = SEC_ERROR_INVALID_ARGS;
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
rv = ssl_PopulateOCSPResponses(sc, data->stapledOCSPResponses);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
rv = ssl_PopulateSignedCertTimestamps(sc, data->signedCertTimestamps);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
PR_APPEND_LINK(&sc->link, &ss->serverCerts);
|
|
|
|
|
|
|
|
/* This one-time setup depends on having the certificate in place. */
|
|
|
|
rv = ssl_OneTimeCertSetup(ss, sc);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
PR_REMOVE_LINK(&sc->link);
|
|
|
|
error_code = PORT_GetError();
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
|
|
|
|
loser:
|
|
|
|
if (sc) {
|
|
|
|
ssl_FreeServerCert(sc);
|
|
|
|
}
|
|
|
|
/* This is the only way any of the calls above can fail, except the one time
|
|
|
|
* setup, which doesn't land here. */
|
|
|
|
PORT_SetError(error_code);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SSLAuthType
|
2016-06-02 23:33:04 +03:00
|
|
|
ssl_GetEcdhAuthType(CERTCertificate *cert)
|
|
|
|
{
|
2016-04-27 15:51:59 +03:00
|
|
|
SECOidTag sigTag = SECOID_GetAlgorithmTag(&cert->signature);
|
|
|
|
switch (sigTag) {
|
|
|
|
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
|
|
|
|
return ssl_auth_ecdh_rsa;
|
|
|
|
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
|
|
|
|
case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
|
|
|
|
case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
|
|
|
|
case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
|
|
|
|
case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
|
|
|
|
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
|
|
|
|
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
|
|
|
|
return ssl_auth_ecdh_ecdsa;
|
|
|
|
default:
|
|
|
|
return ssl_auth_null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function examines the type of certificate and its key usage and
|
|
|
|
* configures a certificate based on that information. For RSA certificates
|
|
|
|
* only, this can mean that two certificates are configured.
|
|
|
|
*
|
|
|
|
* If the optional data argument contains an authType value other than
|
|
|
|
* ssl_auth_null, then only that slot will be used. If that choice is invalid,
|
|
|
|
* then this will fail. */
|
|
|
|
static SECStatus
|
|
|
|
ssl_ConfigCertByUsage(sslSocket *ss, CERTCertificate *cert,
|
|
|
|
ssl3KeyPair *keyPair, const SSLExtraServerCertData *data)
|
|
|
|
{
|
|
|
|
SECStatus rv = SECFailure;
|
|
|
|
SSLExtraServerCertData arg = {
|
|
|
|
ssl_auth_null, NULL, NULL, NULL
|
|
|
|
};
|
|
|
|
SECOidTag tag;
|
|
|
|
|
|
|
|
if (data) {
|
|
|
|
/* Take a (shallow) copy so that we can play with it */
|
|
|
|
memcpy(&arg, data, sizeof(arg));
|
|
|
|
}
|
|
|
|
tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
|
|
|
|
switch (tag) {
|
|
|
|
case SEC_OID_X500_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
|
|
|
if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
|
|
|
if ((cert->keyUsage & KU_KEY_ENCIPHERMENT) &&
|
|
|
|
arg.authType == ssl_auth_null) {
|
|
|
|
/* Two usages is bad form, but there are enough dual-usage RSA
|
|
|
|
* certs that we can't really break by limiting this to one.
|
|
|
|
* Configure both slots only if no explicit slot was set. */
|
|
|
|
arg.authType = ssl_auth_rsa_decrypt;
|
|
|
|
rv = ssl_ConfigCert(ss, cert, keyPair, &arg);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
arg.authType = ssl_auth_rsa_sign;
|
|
|
|
} else if (cert->keyUsage & KU_KEY_ENCIPHERMENT) {
|
|
|
|
arg.authType = ssl_auth_rsa_decrypt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
|
|
|
|
if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
|
|
|
arg.authType = ssl_auth_rsa_pss;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SEC_OID_ANSIX9_DSA_SIGNATURE:
|
|
|
|
if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
|
|
|
arg.authType = ssl_auth_dsa;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
|
|
|
if (cert->keyUsage & KU_KEY_ENCIPHERMENT) {
|
|
|
|
if ((cert->keyUsage & KU_DIGITAL_SIGNATURE) &&
|
|
|
|
arg.authType == ssl_auth_null) {
|
|
|
|
/* See above regarding bad practice. */
|
|
|
|
arg.authType = ssl_auth_ecdsa;
|
|
|
|
rv = ssl_ConfigCert(ss, cert, keyPair, &arg);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
arg.authType = ssl_GetEcdhAuthType(cert);
|
|
|
|
} else if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
|
|
|
arg.authType = ssl_auth_ecdsa;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that we successfully picked an authType */
|
|
|
|
if (arg.authType == ssl_auth_null) {
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
/* |data->authType| has to either agree or be ssl_auth_null. */
|
2016-06-02 23:33:04 +03:00
|
|
|
if (data && data->authType != ssl_auth_null &&
|
|
|
|
data->authType != arg.authType) {
|
2016-04-27 15:51:59 +03:00
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
return ssl_ConfigCert(ss, cert, keyPair, &arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function adopts pubKey and destroys it if things go wrong. */
|
|
|
|
static ssl3KeyPair *
|
|
|
|
ssl_MakeKeyPairForCert(SECKEYPrivateKey *key, SECKEYPublicKey *pubKey)
|
|
|
|
{
|
|
|
|
ssl3KeyPair *keyPair = NULL;
|
|
|
|
SECKEYPrivateKey *privKeyCopy = NULL;
|
|
|
|
PK11SlotInfo *bestSlot;
|
|
|
|
|
|
|
|
if (key->pkcs11Slot) {
|
|
|
|
bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
|
|
|
|
if (bestSlot) {
|
|
|
|
privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
|
|
|
|
PK11_FreeSlot(bestSlot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!privKeyCopy) {
|
|
|
|
CK_MECHANISM_TYPE keyMech = PK11_MapSignKeyType(key->keyType);
|
|
|
|
/* XXX Maybe should be bestSlotMultiple? */
|
|
|
|
bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
|
|
|
|
if (bestSlot) {
|
|
|
|
privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
|
|
|
|
PK11_FreeSlot(bestSlot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!privKeyCopy) {
|
|
|
|
privKeyCopy = SECKEY_CopyPrivateKey(key);
|
|
|
|
}
|
|
|
|
if (privKeyCopy) {
|
|
|
|
keyPair = ssl3_NewKeyPair(privKeyCopy, pubKey);
|
|
|
|
}
|
|
|
|
if (!keyPair) {
|
|
|
|
if (privKeyCopy) {
|
|
|
|
SECKEY_DestroyPrivateKey(privKeyCopy);
|
|
|
|
}
|
|
|
|
/* We adopted the public key, so we're responsible. */
|
|
|
|
if (pubKey) {
|
|
|
|
SECKEY_DestroyPublicKey(pubKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return keyPair;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Configure a certificate and private key.
|
|
|
|
*
|
|
|
|
* This function examines the certificate and key to determine which slot (or
|
|
|
|
* slots) to place the information in. As long as certificates are different
|
|
|
|
* (based on having different values of sslServerCertType), then this function
|
|
|
|
* can be called multiple times and the certificates will all be remembered.
|
|
|
|
*/
|
|
|
|
SECStatus
|
|
|
|
SSL_ConfigServerCert(PRFileDesc *fd, CERTCertificate *cert,
|
|
|
|
SECKEYPrivateKey *key,
|
|
|
|
const SSLExtraServerCertData *data, unsigned int data_len)
|
|
|
|
{
|
|
|
|
sslSocket *ss;
|
|
|
|
SECKEYPublicKey *pubKey;
|
|
|
|
ssl3KeyPair *keyPair;
|
|
|
|
SECStatus rv;
|
|
|
|
SSLExtraServerCertData dataCopy = {
|
|
|
|
ssl_auth_null, NULL, NULL, NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
ss = ssl_FindSocket(fd);
|
|
|
|
if (!ss) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cert || !key) {
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data) {
|
|
|
|
if (data_len > sizeof(dataCopy)) {
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
PORT_Memcpy(&dataCopy, data, data_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
pubKey = CERT_ExtractPublicKey(cert);
|
|
|
|
if (!pubKey) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
keyPair = ssl_MakeKeyPairForCert(key, pubKey);
|
|
|
|
if (!keyPair) {
|
|
|
|
/* pubKey is adopted by ssl_MakeKeyPairForCert() */
|
|
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = ssl_ConfigCertByUsage(ss, cert, keyPair, &dataCopy);
|
|
|
|
ssl3_FreeKeyPair(keyPair);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************/
|
|
|
|
/* Deprecated functions.
|
|
|
|
*
|
|
|
|
* The remainder of this file contains deprecated functions for server
|
|
|
|
* certificate configuration. These configure certificates incorrectly, but in
|
|
|
|
* a way that allows old code to continue working without change. All these
|
|
|
|
* functions create certificate slots based on SSLKEAType values. Some values
|
|
|
|
* of SSLKEAType cause multiple certificates to be configured.
|
|
|
|
*/
|
|
|
|
|
|
|
|
SECStatus
|
|
|
|
SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
|
|
|
|
SECKEYPrivateKey *key, SSLKEAType kea)
|
|
|
|
{
|
|
|
|
return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This implements a limited check that is consistent with the checks performed
|
|
|
|
* by older versions of NSS. This is less rigorous than the checks in
|
|
|
|
* ssl_ConfigCertByUsage(), only checking against the type of key and ignoring
|
|
|
|
* things like usage. */
|
|
|
|
static PRBool
|
|
|
|
ssl_CertSuitableForAuthType(CERTCertificate *cert, SSLAuthType authType)
|
|
|
|
{
|
|
|
|
SECOidTag tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
|
|
|
|
switch (authType) {
|
|
|
|
case ssl_auth_rsa_decrypt:
|
|
|
|
case ssl_auth_rsa_sign:
|
|
|
|
return tag == SEC_OID_X500_RSA_ENCRYPTION ||
|
|
|
|
tag == SEC_OID_PKCS1_RSA_ENCRYPTION;
|
|
|
|
case ssl_auth_dsa:
|
|
|
|
return tag == SEC_OID_ANSIX9_DSA_SIGNATURE;
|
|
|
|
case ssl_auth_ecdsa:
|
|
|
|
case ssl_auth_ecdh_rsa:
|
|
|
|
case ssl_auth_ecdh_ecdsa:
|
|
|
|
return tag == SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
|
|
|
case ssl_auth_null:
|
|
|
|
case ssl_auth_kea:
|
|
|
|
case ssl_auth_rsa_pss: /* not supported with deprecated APIs */
|
|
|
|
return PR_FALSE;
|
|
|
|
default:
|
|
|
|
PORT_Assert(0);
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This finds an existing server cert slot and unlinks it, or it makes a new
|
|
|
|
* server cert slot of the right type. */
|
|
|
|
static sslServerCert *
|
|
|
|
ssl_FindOrMakeCertType(sslSocket *ss, SSLAuthType authType)
|
|
|
|
{
|
|
|
|
sslServerCert *sc;
|
|
|
|
sslServerCertType certType;
|
|
|
|
|
|
|
|
certType.authType = authType;
|
|
|
|
switch (authType) {
|
|
|
|
case ssl_auth_ecdsa:
|
|
|
|
case ssl_auth_ecdh_rsa:
|
|
|
|
case ssl_auth_ecdh_ecdsa:
|
|
|
|
/* Setting the named curve to ec_noName ensures that all EC certificates
|
|
|
|
* are matched when searching for this slot. */
|
|
|
|
certType.u.namedCurve = ec_noName;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sc = ssl_FindServerCert(ss, &certType);
|
|
|
|
if (sc) {
|
|
|
|
PR_REMOVE_LINK(&sc->link);
|
|
|
|
return sc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ssl_NewServerCert(&certType);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ssl_RemoveCertAndKeyByAuthType(sslSocket *ss, SSLAuthType authType)
|
|
|
|
{
|
|
|
|
sslServerCert *sc;
|
|
|
|
|
|
|
|
sc = ssl_FindServerCertByAuthType(ss, authType);
|
|
|
|
if (sc) {
|
|
|
|
(void)ssl_PopulateServerCert(sc, NULL, NULL);
|
|
|
|
(void)ssl_PopulateKeyPair(sc, NULL);
|
|
|
|
/* Leave the entry linked here because the old API expects that. There
|
|
|
|
* might be OCSP stapling values or signed certificate timestamps still
|
|
|
|
* present that will subsequently be used. */
|
|
|
|
/* For ECC certificates, also leave the namedCurve parameter on the slot
|
|
|
|
* unchanged; the value will be updated when a key is added. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_AddCertAndKeyByAuthType(sslSocket *ss, SSLAuthType authType,
|
|
|
|
CERTCertificate *cert,
|
|
|
|
const CERTCertificateList *certChainOpt,
|
|
|
|
ssl3KeyPair *keyPair)
|
|
|
|
{
|
|
|
|
sslServerCert *sc;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
if (!ssl_CertSuitableForAuthType(cert, authType)) {
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc = ssl_FindOrMakeCertType(ss, authType);
|
|
|
|
if (!sc) {
|
|
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
rv = ssl_PopulateKeyPair(sc, keyPair);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
/* Now that we have a key pair, update the details of the slot. Many of the
|
|
|
|
* legacy functions create a slot with a namedCurve of ec_noName, which
|
|
|
|
* makes the slot unusable; this corrects that. */
|
|
|
|
ssl_PopulateCertType(&sc->certType, authType, cert, keyPair);
|
|
|
|
rv = ssl_PopulateServerCert(sc, cert, certChainOpt);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
PR_APPEND_LINK(&sc->link, &ss->serverCerts);
|
|
|
|
return ssl_OneTimeCertSetup(ss, sc);
|
|
|
|
loser:
|
|
|
|
ssl_FreeServerCert(sc);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_AddCertsByKEA(sslSocket *ss, CERTCertificate *cert,
|
|
|
|
const CERTCertificateList *certChainOpt,
|
|
|
|
SECKEYPrivateKey *key, SSLKEAType certType)
|
|
|
|
{
|
|
|
|
SECKEYPublicKey *pubKey;
|
|
|
|
ssl3KeyPair *keyPair;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
pubKey = CERT_ExtractPublicKey(cert);
|
|
|
|
if (!pubKey) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
keyPair = ssl_MakeKeyPairForCert(key, pubKey);
|
|
|
|
if (!keyPair) {
|
|
|
|
/* Note: pubKey is adopted or freed by ssl_MakeKeyPairForCert()
|
|
|
|
* depending on whether it succeeds or not. */
|
|
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (certType) {
|
|
|
|
case ssl_kea_rsa:
|
|
|
|
rv = ssl_AddCertAndKeyByAuthType(ss, ssl_auth_rsa_decrypt,
|
|
|
|
cert, certChainOpt, keyPair);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
rv = ssl_AddCertAndKeyByAuthType(ss, ssl_auth_rsa_sign,
|
|
|
|
cert, certChainOpt, keyPair);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ssl_kea_dh:
|
|
|
|
rv = ssl_AddCertAndKeyByAuthType(ss, ssl_auth_dsa,
|
|
|
|
cert, certChainOpt, keyPair);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ssl_kea_ecdh:
|
|
|
|
rv = ssl_AddCertAndKeyByAuthType(ss, ssl_auth_ecdsa,
|
|
|
|
cert, certChainOpt, keyPair);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
rv = ssl_AddCertAndKeyByAuthType(ss, ssl_GetEcdhAuthType(cert),
|
|
|
|
cert, certChainOpt, keyPair);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
rv = SECFailure;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssl3_FreeKeyPair(keyPair);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public deprecated function */
|
|
|
|
SECStatus
|
|
|
|
SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
|
|
|
|
const CERTCertificateList *certChainOpt,
|
|
|
|
SECKEYPrivateKey *key, SSLKEAType certType)
|
|
|
|
{
|
|
|
|
sslSocket *ss;
|
|
|
|
|
|
|
|
ss = ssl_FindSocket(fd);
|
|
|
|
if (!ss) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cert != !key) { /* Configure both, or neither */
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cert) {
|
|
|
|
switch (certType) {
|
|
|
|
case ssl_kea_rsa:
|
|
|
|
ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_rsa_decrypt);
|
|
|
|
ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_rsa_sign);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ssl_kea_dh:
|
|
|
|
ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_dsa);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ssl_kea_ecdh:
|
|
|
|
ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_ecdsa);
|
|
|
|
ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_ecdh_rsa);
|
|
|
|
ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_ecdh_ecdsa);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ssl_AddCertsByKEA(ss, cert, certChainOpt, key, certType);
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_SetOCSPResponsesInSlot(sslSocket *ss, SSLAuthType authType,
|
|
|
|
const SECItemArray *responses)
|
|
|
|
{
|
|
|
|
sslServerCert *sc;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
sc = ssl_FindOrMakeCertType(ss, authType);
|
|
|
|
if (!sc) {
|
|
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
rv = ssl_PopulateOCSPResponses(sc, responses);
|
|
|
|
if (rv == SECSuccess) {
|
|
|
|
PR_APPEND_LINK(&sc->link, &ss->serverCerts);
|
|
|
|
} else {
|
|
|
|
ssl_FreeServerCert(sc);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public deprecated function */
|
|
|
|
SECStatus
|
|
|
|
SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
|
|
|
|
SSLKEAType certType)
|
|
|
|
{
|
|
|
|
sslSocket *ss;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
ss = ssl_FindSocket(fd);
|
|
|
|
if (!ss) {
|
|
|
|
SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses",
|
|
|
|
SSL_GETPID(), fd));
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (certType) {
|
|
|
|
case ssl_kea_rsa:
|
|
|
|
rv = ssl_SetOCSPResponsesInSlot(ss, ssl_auth_rsa_decrypt, responses);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
return ssl_SetOCSPResponsesInSlot(ss, ssl_auth_rsa_sign, responses);
|
|
|
|
|
|
|
|
case ssl_kea_dh:
|
|
|
|
return ssl_SetOCSPResponsesInSlot(ss, ssl_auth_dsa, responses);
|
|
|
|
|
|
|
|
case ssl_kea_ecdh:
|
|
|
|
rv = ssl_SetOCSPResponsesInSlot(ss, ssl_auth_ecdsa, responses);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
rv = ssl_SetOCSPResponsesInSlot(ss, ssl_auth_ecdh_rsa, responses);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
return ssl_SetOCSPResponsesInSlot(ss, ssl_auth_ecdh_ecdsa, responses);
|
|
|
|
|
|
|
|
default:
|
|
|
|
SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetStapledOCSPResponses",
|
|
|
|
SSL_GETPID(), fd));
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECStatus
|
|
|
|
ssl_SetSignedTimestampsInSlot(sslSocket *ss, SSLAuthType authType,
|
|
|
|
const SECItem *scts)
|
|
|
|
{
|
|
|
|
sslServerCert *sc;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
sc = ssl_FindOrMakeCertType(ss, authType);
|
|
|
|
if (!sc) {
|
|
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
rv = ssl_PopulateSignedCertTimestamps(sc, scts);
|
|
|
|
if (rv == SECSuccess) {
|
|
|
|
PR_APPEND_LINK(&sc->link, &ss->serverCerts);
|
|
|
|
} else {
|
|
|
|
ssl_FreeServerCert(sc);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public deprecated function */
|
|
|
|
SECStatus
|
|
|
|
SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts,
|
|
|
|
SSLKEAType certType)
|
|
|
|
{
|
|
|
|
sslSocket *ss;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
ss = ssl_FindSocket(fd);
|
|
|
|
if (!ss) {
|
|
|
|
SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSignedCertTimestamps",
|
|
|
|
SSL_GETPID(), fd));
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (certType) {
|
|
|
|
case ssl_kea_rsa:
|
|
|
|
rv = ssl_SetSignedTimestampsInSlot(ss, ssl_auth_rsa_decrypt, scts);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
return ssl_SetSignedTimestampsInSlot(ss, ssl_auth_rsa_sign, scts);
|
|
|
|
|
|
|
|
case ssl_kea_dh:
|
|
|
|
return ssl_SetSignedTimestampsInSlot(ss, ssl_auth_dsa, scts);
|
|
|
|
|
|
|
|
case ssl_kea_ecdh:
|
|
|
|
rv = ssl_SetSignedTimestampsInSlot(ss, ssl_auth_ecdsa, scts);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
rv = ssl_SetSignedTimestampsInSlot(ss, ssl_auth_ecdh_rsa, scts);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
return ssl_SetSignedTimestampsInSlot(ss, ssl_auth_ecdh_ecdsa, scts);
|
|
|
|
|
|
|
|
default:
|
|
|
|
SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetSignedCertTimestamps",
|
|
|
|
SSL_GETPID(), fd));
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public deprecated function. */
|
|
|
|
SSLKEAType
|
|
|
|
NSS_FindCertKEAType(CERTCertificate *cert)
|
|
|
|
{
|
|
|
|
int tag;
|
|
|
|
|
|
|
|
if (!cert)
|
|
|
|
return ssl_kea_null;
|
|
|
|
|
|
|
|
tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
|
|
|
|
switch (tag) {
|
|
|
|
case SEC_OID_X500_RSA_ENCRYPTION:
|
|
|
|
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
|
|
|
return ssl_kea_rsa;
|
|
|
|
case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */
|
|
|
|
case SEC_OID_X942_DIFFIE_HELMAN_KEY:
|
|
|
|
return ssl_kea_dh;
|
|
|
|
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
|
|
|
return ssl_kea_ecdh;
|
|
|
|
default:
|
|
|
|
return ssl_kea_null;
|
|
|
|
}
|
|
|
|
}
|