Merge mozilla-central to autoland. CLOSED TREE

This commit is contained in:
Butkovits Atila 2022-01-12 23:40:05 +02:00
Родитель ebb37d7349 435a77f1a1
Коммит 3a214de2f6
17 изменённых файлов: 784 добавлений и 250 удалений

Просмотреть файл

@ -330,7 +330,12 @@ mozilla::ipc::IPCResult SocketProcessParent::RecvGetTLSClientCert(
RefPtr<nsIX509Cert> clientCert;
if (aClientCert) {
clientCert = new nsNSSCertificate(std::move(aClientCert->data()));
clientCert = nsNSSCertificate::ConstructFromDER(
BitwiseCast<char*, uint8_t*>(aClientCert->data().Elements()),
aClientCert->data().Length());
if (!clientCert) {
return IPC_OK();
}
}
ClientAuthInfo info(aHostName, aOriginAttributes, aPort, aProviderFlags,

Просмотреть файл

@ -1322,18 +1322,28 @@ nsresult OpenSignedAppFile(AppTrustedRoot aTrustedRoot, nsIFile* aJarFile,
if (aSignerCert) {
// The COSE certificate is authoritative.
if (aPolicy.COSERequired() || !coseCertDER.IsEmpty()) {
if (coseCertDER.IsEmpty()) {
if (coseCertDER.IsEmpty() ||
coseCertDER.Length() > std::numeric_limits<int>::max()) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509Cert> signerCert(nsNSSCertificate::ConstructFromDER(
reinterpret_cast<char*>(coseCertDER.Elements()),
coseCertDER.Length()));
if (!signerCert) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509Cert> signerCert(
new nsNSSCertificate(std::move(coseCertDER)));
signerCert.forget(aSignerCert);
} else {
if (pkcs7CertDER.IsEmpty()) {
if (pkcs7CertDER.IsEmpty() ||
pkcs7CertDER.Length() > std::numeric_limits<int>::max()) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509Cert> signerCert(nsNSSCertificate::ConstructFromDER(
reinterpret_cast<char*>(pkcs7CertDER.Elements()),
pkcs7CertDER.Length()));
if (!signerCert) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509Cert> signerCert(
new nsNSSCertificate(std::move(pkcs7CertDER)));
signerCert.forget(aSignerCert);
}
}

Просмотреть файл

@ -242,8 +242,16 @@ void CommonSocketControl::RebuildCertificateInfoFromSSLTokenCache() {
return;
}
RefPtr<nsNSSCertificate> nssc =
new nsNSSCertificate(std::move(info.mServerCertBytes));
RefPtr<nsNSSCertificate> nssc = nsNSSCertificate::ConstructFromDER(
BitwiseCast<char*, uint8_t*>(info.mServerCertBytes.Elements()),
info.mServerCertBytes.Length());
if (!nssc) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("RebuildCertificateInfoFromSSLTokenCache failed to construct "
"server cert"));
return;
}
SetServerCert(nssc, info.mEVStatus);
SetCertificateTransparencyStatus(info.mCertificateTransparencyStatus);
if (info.mSucceededCertChainBytes) {

Просмотреть файл

@ -268,7 +268,7 @@ class LocalCertGetTask final : public LocalCertTask {
if (!cert) {
return NS_ERROR_FAILURE;
}
mCert = new nsNSSCertificate(cert.get());
mCert = nsNSSCertificate::Create(cert.get());
return NS_OK;
}

Просмотреть файл

@ -948,7 +948,11 @@ PRErrorCode AuthCertificateParseResults(
if (overrideService) {
bool haveOverride;
bool isTemporaryOverride; // we don't care
RefPtr<nsIX509Cert> nssCert(new nsNSSCertificate(aCert.get()));
RefPtr<nsIX509Cert> nssCert(nsNSSCertificate::Create(aCert.get()));
if (!nssCert) {
MOZ_ASSERT(false, "nsNSSCertificate::Create failed");
return SEC_ERROR_NO_MEMORY;
}
nsresult rv = overrideService->HasMatchingOverride(
aHostName, aPort, aOriginAttributes, nssCert, &overrideBits,
&isTemporaryOverride, &haveOverride);
@ -1086,7 +1090,7 @@ SSLServerCertVerificationJob::Run() {
mProviderFlags, mTime, mCertVerifierFlags, builtChainBytesArray, evStatus,
certificateTransparencyInfo, isCertChainRootBuiltInRoot);
RefPtr<nsNSSCertificate> nsc = new nsNSSCertificate(mCert.get());
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(mCert.get());
if (rv == Success) {
Telemetry::AccumulateTimeDelta(
Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_MOZILLAPKIX, jobStartTime,

Просмотреть файл

@ -985,7 +985,11 @@ static nsresult CreateCertChain(nsTArray<RefPtr<nsIX509Cert>>& aOutput,
nsTArray<nsTArray<uint8_t>> certList = std::move(aCertList);
aOutput.Clear();
for (auto& certBytes : certList) {
RefPtr<nsIX509Cert> cert = new nsNSSCertificate(std::move(certBytes));
RefPtr<nsIX509Cert> cert = nsNSSCertificate::ConstructFromDER(
BitwiseCast<char*, uint8_t*>(certBytes.Elements()), certBytes.Length());
if (!cert) {
return NS_ERROR_FAILURE;
}
aOutput.AppendElement(cert);
}
return NS_OK;

Просмотреть файл

@ -35,7 +35,7 @@ ipc::IPCResult VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertSuccess(
("[%p] VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertSuccess",
this));
RefPtr<nsNSSCertificate> nsc = new nsNSSCertificate(mCert.get());
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(mCert.get());
nsTArray<nsTArray<uint8_t>> certBytesArray;
for (auto& cert : aBuiltCertChain) {
certBytesArray.AppendElement(std::move(cert.data()));
@ -56,7 +56,7 @@ ipc::IPCResult VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertFailure(
"aCollectedErrors=%u",
this, aFinalError, aCollectedErrors));
RefPtr<nsNSSCertificate> nsc = new nsNSSCertificate(mCert.get());
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(mCert.get());
mResultTask->Dispatch(
nsc, nsTArray<nsTArray<uint8_t>>(), std::move(mPeerCertChain),
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE,

Просмотреть файл

@ -237,9 +237,15 @@ nsresult CheckForPreferredCertificate(const nsACString& aHostName,
return NS_ERROR_UNEXPECTED;
}
nsTArray<uint8_t> derArray(::CFDataGetBytePtr(der.get()),
::CFDataGetLength(der.get()));
nsCOMPtr<nsIX509Cert> cert(new nsNSSCertificate(std::move(derArray)));
nsCOMPtr<nsIX509Cert> cert(nsNSSCertificate::ConstructFromDER(
// ConstructFromDER is not const-correct so we have to cast away the
// const.
const_cast<char*>(
reinterpret_cast<const char*>(::CFDataGetBytePtr(der.get()))),
::CFDataGetLength(der.get())));
if (!cert) {
return NS_ERROR_FAILURE;
}
return cert->GetDbKey(aCertDBKey);
}
#endif

Просмотреть файл

@ -1107,7 +1107,7 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
("HandshakeCallback: couldn't rebuild verified certificate info"));
}
RefPtr<nsNSSCertificate> nssc(new nsNSSCertificate(cert.get()));
RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(cert.get()));
if (rv == Success && evStatus == EVStatus::EV) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback using NEW cert %p (is EV)", nssc.get()));

Просмотреть файл

@ -63,35 +63,59 @@ extern LazyLogModule gPIPNSSLog;
NS_IMPL_ISUPPORTS(nsNSSCertificate, nsIX509Cert, nsISerializable, nsIClassInfo)
nsNSSCertificate::nsNSSCertificate()
: mCert(Nothing()), mCertType(CERT_TYPE_NOT_YET_INITIALIZED) {}
/*static*/
nsNSSCertificate* nsNSSCertificate::Create(CERTCertificate* cert) {
if (cert)
return new nsNSSCertificate(cert);
else
return new nsNSSCertificate();
}
nsNSSCertificate* nsNSSCertificate::ConstructFromDER(char* certDER,
int derLen) {
nsNSSCertificate* newObject = nsNSSCertificate::Create();
if (newObject && !newObject->InitFromDER(certDER, derLen)) {
delete newObject;
newObject = nullptr;
}
return newObject;
}
bool nsNSSCertificate::InitFromDER(char* certDER, int derLen) {
if (!certDER || !derLen) return false;
CERTCertificate* aCert = CERT_DecodeCertFromPackage(certDER, derLen);
if (!aCert) {
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (XRE_GetProcessType() == GeckoProcessType_Content) {
MOZ_CRASH_UNSAFE_PRINTF("CERT_DecodeCertFromPackage failed in child: %d",
PR_GetError());
}
#endif
return false;
}
if (!aCert->dbhandle) {
aCert->dbhandle = CERT_GetDefaultCertDB();
}
mCert.reset(aCert);
return true;
}
nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert)
: mCert(Nothing()), mCertType(CERT_TYPE_NOT_YET_INITIALIZED) {
: mCert(nullptr), mCertType(CERT_TYPE_NOT_YET_INITIALIZED) {
if (cert) {
mDER.AppendElements(cert->derCert.data, cert->derCert.len);
mCert.emplace(UniqueCERTCertificate(CERT_DupCertificate(cert)));
mCert.reset(CERT_DupCertificate(cert));
}
}
nsNSSCertificate::nsNSSCertificate(nsTArray<uint8_t>&& der)
: mDER(std::move(der)),
mCert(Nothing()),
mCertType(CERT_TYPE_NOT_YET_INITIALIZED) {}
nsNSSCertificate::nsNSSCertificate()
: mCert(nullptr), mCertType(CERT_TYPE_NOT_YET_INITIALIZED) {}
nsresult nsNSSCertificate::InstantiateCert() {
SECItem derItem = {siBuffer, mDER.Elements(),
static_cast<unsigned int>(mDER.Length())};
UniqueCERTCertificate cert(CERT_NewTempCertificate(
CERT_GetDefaultCertDB(), &derItem, nullptr, false, true));
if (!cert) {
return NS_ERROR_FAILURE;
}
mCert.emplace(std::move(cert));
return NS_OK;
}
static uint32_t getCertType(UniqueCERTCertificate& cert) {
static uint32_t getCertType(CERTCertificate* cert) {
nsNSSCertTrust trust(cert->trust);
if (cert->nickname && trust.HasAnyUser()) {
return nsIX509Cert::USER_CERT;
@ -105,7 +129,7 @@ static uint32_t getCertType(UniqueCERTCertificate& cert) {
if (trust.HasPeer(false, true) && cert->emailAddr) {
return nsIX509Cert::EMAIL_CERT;
}
if (CERT_IsCACert(cert.get(), nullptr)) {
if (CERT_IsCACert(cert, nullptr)) {
return nsIX509Cert::CA_CERT;
}
if (cert->emailAddr) {
@ -117,13 +141,7 @@ static uint32_t getCertType(UniqueCERTCertificate& cert) {
nsresult nsNSSCertificate::GetCertType(uint32_t* aCertType) {
if (mCertType == CERT_TYPE_NOT_YET_INITIALIZED) {
// only determine cert type once and cache it
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
}
mCertType = getCertType(*mCert);
mCertType = getCertType(mCert.get());
}
*aCertType = mCertType;
return NS_OK;
@ -134,7 +152,7 @@ nsNSSCertificate::GetIsBuiltInRoot(bool* aIsBuiltInRoot) {
NS_ENSURE_ARG(aIsBuiltInRoot);
pkix::Input certInput;
pkix::Result rv = certInput.Init(mDER.Elements(), mDER.Length());
pkix::Result rv = certInput.Init(mCert->derCert.data, mCert->derCert.len);
if (rv != pkix::Result::Success) {
return NS_ERROR_FAILURE;
}
@ -151,7 +169,7 @@ nsNSSCertificate::GetDbKey(nsACString& aDbKey) {
static_assert(sizeof(uint32_t) == 4, "type size consistency check");
pkix::Input certInput;
pkix::Result result = certInput.Init(mDER.Elements(), mDER.Length());
pkix::Result result = certInput.Init(mCert->derCert.data, mCert->derCert.len);
if (result != pkix::Result::Success) {
return NS_ERROR_INVALID_ARG;
}
@ -195,17 +213,14 @@ NS_IMETHODIMP
nsNSSCertificate::GetDisplayName(nsAString& aDisplayName) {
aDisplayName.Truncate();
MOZ_ASSERT(mCert, "mCert should not be null in GetDisplayName");
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
return NS_ERROR_FAILURE;
}
UniquePORTString commonName(CERT_GetCommonName(&(*mCert)->subject));
UniquePORTString organizationalUnitName(
CERT_GetOrgUnitName(&(*mCert)->subject));
UniquePORTString organizationName(CERT_GetOrgName(&(*mCert)->subject));
UniquePORTString commonName(CERT_GetCommonName(&mCert->subject));
UniquePORTString organizationalUnitName(CERT_GetOrgUnitName(&mCert->subject));
UniquePORTString organizationName(CERT_GetOrgName(&mCert->subject));
bool isBuiltInRoot;
nsresult rv = GetIsBuiltInRoot(&isBuiltInRoot);
@ -226,7 +241,7 @@ nsNSSCertificate::GetDisplayName(nsAString& aDisplayName) {
// (the subject really shouldn't be empty), an empty string is returned.
nsAutoCString builtInRootNickname;
if (isBuiltInRoot) {
nsAutoCString fullNickname((*mCert)->nickname);
nsAutoCString fullNickname(mCert->nickname);
int32_t index = fullNickname.Find(":");
if (index != kNotFound) {
// Substring will gracefully handle the case where index is the last
@ -239,7 +254,7 @@ nsNSSCertificate::GetDisplayName(nsAString& aDisplayName) {
const char* nameOptions[] = {
builtInRootNickname.get(), commonName.get(),
organizationalUnitName.get(), organizationName.get(),
(*mCert)->subjectName, (*mCert)->emailAddr};
mCert->subjectName, mCert->emailAddr};
for (auto nameOption : nameOptions) {
if (nameOption) {
@ -256,14 +271,8 @@ nsNSSCertificate::GetDisplayName(nsAString& aDisplayName) {
NS_IMETHODIMP
nsNSSCertificate::GetEmailAddress(nsAString& aEmailAddress) {
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
}
if ((*mCert)->emailAddr) {
CopyUTF8toUTF16(MakeStringSpan((*mCert)->emailAddr), aEmailAddress);
if (mCert->emailAddr) {
CopyUTF8toUTF16(MakeStringSpan(mCert->emailAddr), aEmailAddress);
} else {
GetPIPNSSBundleString("CertNoEmailAddress", aEmailAddress);
}
@ -272,22 +281,16 @@ nsNSSCertificate::GetEmailAddress(nsAString& aEmailAddress) {
NS_IMETHODIMP
nsNSSCertificate::GetEmailAddresses(nsTArray<nsString>& aAddresses) {
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
}
uint32_t length = 0;
for (const char* aAddr = CERT_GetFirstEmailAddress((*mCert).get()); aAddr;
aAddr = CERT_GetNextEmailAddress((*mCert).get(), aAddr)) {
for (const char* aAddr = CERT_GetFirstEmailAddress(mCert.get()); aAddr;
aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr)) {
++(length);
}
aAddresses.SetCapacity(length);
for (const char* aAddr = CERT_GetFirstEmailAddress((*mCert).get()); aAddr;
aAddr = CERT_GetNextEmailAddress((*mCert).get(), aAddr)) {
for (const char* aAddr = CERT_GetFirstEmailAddress(mCert.get()); aAddr;
aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr)) {
CopyASCIItoUTF16(MakeStringSpan(aAddr), *aAddresses.AppendElement());
}
@ -300,14 +303,8 @@ nsNSSCertificate::ContainsEmailAddress(const nsAString& aEmailAddress,
NS_ENSURE_ARG(result);
*result = false;
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
}
for (const char* aAddr = CERT_GetFirstEmailAddress((*mCert).get()); aAddr;
aAddr = CERT_GetNextEmailAddress((*mCert).get(), aAddr)) {
for (const char* aAddr = CERT_GetFirstEmailAddress(mCert.get()); aAddr;
aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr)) {
nsAutoString certAddr;
LossyUTF8ToUTF16(aAddr, strlen(aAddr), certAddr);
ToLowerCase(certAddr);
@ -327,113 +324,84 @@ nsNSSCertificate::ContainsEmailAddress(const nsAString& aEmailAddress,
NS_IMETHODIMP
nsNSSCertificate::GetCommonName(nsAString& aCommonName) {
aCommonName.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
if (mCert) {
UniquePORTString commonName(CERT_GetCommonName(&mCert->subject));
if (commonName) {
LossyUTF8ToUTF16(commonName.get(), strlen(commonName.get()), aCommonName);
}
}
UniquePORTString commonName(CERT_GetCommonName(&(*mCert)->subject));
if (commonName) {
LossyUTF8ToUTF16(commonName.get(), strlen(commonName.get()), aCommonName);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetOrganization(nsAString& aOrganization) {
aOrganization.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
if (mCert) {
UniquePORTString organization(CERT_GetOrgName(&mCert->subject));
if (organization) {
LossyUTF8ToUTF16(organization.get(), strlen(organization.get()),
aOrganization);
}
}
UniquePORTString organization(CERT_GetOrgName(&(*mCert)->subject));
if (organization) {
LossyUTF8ToUTF16(organization.get(), strlen(organization.get()),
aOrganization);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetIssuerCommonName(nsAString& aCommonName) {
aCommonName.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
if (mCert) {
UniquePORTString commonName(CERT_GetCommonName(&mCert->issuer));
if (commonName) {
LossyUTF8ToUTF16(commonName.get(), strlen(commonName.get()), aCommonName);
}
}
UniquePORTString commonName(CERT_GetCommonName(&(*mCert)->issuer));
if (commonName) {
LossyUTF8ToUTF16(commonName.get(), strlen(commonName.get()), aCommonName);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetIssuerOrganization(nsAString& aOrganization) {
aOrganization.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
if (mCert) {
UniquePORTString organization(CERT_GetOrgName(&mCert->issuer));
if (organization) {
LossyUTF8ToUTF16(organization.get(), strlen(organization.get()),
aOrganization);
}
}
UniquePORTString organization(CERT_GetOrgName(&(*mCert)->issuer));
if (organization) {
LossyUTF8ToUTF16(organization.get(), strlen(organization.get()),
aOrganization);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetIssuerOrganizationUnit(nsAString& aOrganizationUnit) {
aOrganizationUnit.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
if (mCert) {
UniquePORTString organizationUnit(CERT_GetOrgUnitName(&mCert->issuer));
if (organizationUnit) {
LossyUTF8ToUTF16(organizationUnit.get(), strlen(organizationUnit.get()),
aOrganizationUnit);
}
}
UniquePORTString organizationUnit(CERT_GetOrgUnitName(&(*mCert)->issuer));
if (organizationUnit) {
LossyUTF8ToUTF16(organizationUnit.get(), strlen(organizationUnit.get()),
aOrganizationUnit);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetOrganizationalUnit(nsAString& aOrganizationalUnit) {
aOrganizationalUnit.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
if (mCert) {
UniquePORTString orgunit(CERT_GetOrgUnitName(&mCert->subject));
if (orgunit) {
LossyUTF8ToUTF16(orgunit.get(), strlen(orgunit.get()),
aOrganizationalUnit);
}
}
UniquePORTString orgunit(CERT_GetOrgUnitName(&(*mCert)->subject));
if (orgunit) {
LossyUTF8ToUTF16(orgunit.get(), strlen(orgunit.get()), aOrganizationalUnit);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetSubjectName(nsAString& _subjectName) {
_subjectName.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
}
if ((*mCert)->subjectName) {
LossyUTF8ToUTF16((*mCert)->subjectName, strlen((*mCert)->subjectName),
if (mCert->subjectName) {
LossyUTF8ToUTF16(mCert->subjectName, strlen(mCert->subjectName),
_subjectName);
}
return NS_OK;
@ -442,15 +410,8 @@ nsNSSCertificate::GetSubjectName(nsAString& _subjectName) {
NS_IMETHODIMP
nsNSSCertificate::GetIssuerName(nsAString& _issuerName) {
_issuerName.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
}
if ((*mCert)->issuerName) {
LossyUTF8ToUTF16((*mCert)->issuerName, strlen((*mCert)->issuerName),
_issuerName);
if (mCert->issuerName) {
LossyUTF8ToUTF16(mCert->issuerName, strlen(mCert->issuerName), _issuerName);
}
return NS_OK;
}
@ -458,14 +419,8 @@ nsNSSCertificate::GetIssuerName(nsAString& _issuerName) {
NS_IMETHODIMP
nsNSSCertificate::GetSerialNumber(nsAString& _serialNumber) {
_serialNumber.Truncate();
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
}
UniquePORTString tmpstr(
CERT_Hexify(&(*mCert)->serialNumber, true /* use colon delimiters */));
CERT_Hexify(&mCert->serialNumber, true /* use colon delimiters */));
if (tmpstr) {
_serialNumber = NS_ConvertASCIItoUTF16(tmpstr.get());
return NS_OK;
@ -477,8 +432,8 @@ nsresult nsNSSCertificate::GetCertificateHash(nsAString& aFingerprint,
SECOidTag aHashAlg) {
aFingerprint.Truncate();
nsTArray<uint8_t> digestArray;
nsresult rv =
Digest::DigestBuf(aHashAlg, mDER.Elements(), mDER.Length(), digestArray);
nsresult rv = Digest::DigestBuf(aHashAlg, mCert->derCert.data,
mCert->derCert.len, digestArray);
if (NS_FAILED(rv)) {
return rv;
}
@ -507,18 +462,16 @@ nsNSSCertificate::GetSha1Fingerprint(nsAString& _sha1Fingerprint) {
NS_IMETHODIMP
nsNSSCertificate::GetTokenName(nsAString& aTokenName) {
MOZ_ASSERT(mCert);
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return rv;
}
return NS_ERROR_FAILURE;
}
UniquePK11SlotInfo internalSlot(PK11_GetInternalSlot());
if (!internalSlot) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPK11Token> token(
new nsPK11Token((*mCert)->slot ? (*mCert)->slot : internalSlot.get()));
new nsPK11Token(mCert->slot ? mCert->slot : internalSlot.get()));
nsAutoCString tmp;
nsresult rv = token->GetTokenName(tmp);
if (NS_FAILED(rv)) {
@ -534,7 +487,7 @@ nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(
aSha256SPKIDigest.Truncate();
pkix::Input certInput;
pkix::Result result = certInput.Init(mDER.Elements(), mDER.Length());
pkix::Result result = certInput.Init(mCert->derCert.data, mCert->derCert.len);
if (result != pkix::Result::Success) {
return NS_ERROR_INVALID_ARG;
}
@ -553,7 +506,7 @@ nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(
return rv;
}
rv = Base64Encode(nsDependentCSubstring(
reinterpret_cast<const char*>(digestArray.Elements()),
BitwiseCast<char*, uint8_t*>(digestArray.Elements()),
digestArray.Length()),
aSha256SPKIDigest);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -564,37 +517,40 @@ nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(
NS_IMETHODIMP
nsNSSCertificate::GetRawDER(nsTArray<uint8_t>& aArray) {
aArray.SetLength(mDER.Length());
memcpy(aArray.Elements(), mDER.Elements(), mDER.Length());
return NS_OK;
if (mCert) {
aArray.SetLength(mCert->derCert.len);
memcpy(aArray.Elements(), mCert->derCert.data, mCert->derCert.len);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsNSSCertificate::GetBase64DERString(nsACString& base64DERString) {
nsDependentCSubstring derString(
reinterpret_cast<const char*>(mDER.Elements()), mDER.Length());
reinterpret_cast<const char*>(mCert->derCert.data), mCert->derCert.len);
nsresult rv = Base64Encode(derString, base64DERString);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
CERTCertificate* nsNSSCertificate::GetCert() {
if (!mCert) {
nsresult rv = InstantiateCert();
if (NS_FAILED(rv)) {
return nullptr;
}
}
return CERT_DupCertificate((*mCert).get());
return (mCert) ? CERT_DupCertificate(mCert.get()) : nullptr;
}
NS_IMETHODIMP
nsNSSCertificate::GetValidity(nsIX509CertValidity** aValidity) {
NS_ENSURE_ARG(aValidity);
if (!mCert) {
return NS_ERROR_FAILURE;
}
pkix::Input certInput;
pkix::Result rv = certInput.Init(mDER.Elements(), mDER.Length());
pkix::Result rv = certInput.Init(mCert->derCert.data, mCert->derCert.len);
if (rv != pkix::Success) {
return NS_ERROR_FAILURE;
}
@ -603,29 +559,108 @@ nsNSSCertificate::GetValidity(nsIX509CertValidity** aValidity) {
return NS_OK;
}
namespace mozilla {
// TODO(bug 1036065): It seems like we only construct CERTCertLists for the
// purpose of constructing nsNSSCertLists, so maybe we should change this
// function to output an nsNSSCertList instead.
SECStatus ConstructCERTCertListFromReversedDERArray(
const mozilla::pkix::DERArray& certArray,
/*out*/ UniqueCERTCertList& certList) {
certList = UniqueCERTCertList(CERT_NewCertList());
if (!certList) {
return SECFailure;
}
CERTCertDBHandle* certDB(CERT_GetDefaultCertDB()); // non-owning
size_t numCerts = certArray.GetLength();
for (size_t i = 0; i < numCerts; ++i) {
SECItem certDER(UnsafeMapInputToSECItem(*certArray.GetDER(i)));
UniqueCERTCertificate cert(
CERT_NewTempCertificate(certDB, &certDER, nullptr, false, true));
if (!cert) {
return SECFailure;
}
// certArray is ordered with the root first, but we want the resulting
// certList to have the root last.
if (CERT_AddCertToListHead(certList.get(), cert.get()) != SECSuccess) {
return SECFailure;
}
Unused << cert.release(); // cert is now owned by certList.
}
return SECSuccess;
}
} // namespace mozilla
nsresult nsNSSCertificate::GetIntermediatesAsDER(
/* in */ const nsTArray<RefPtr<nsIX509Cert>>& aCertList,
/* out */ nsTArray<nsTArray<uint8_t>>& aIntermediates) {
if (aCertList.Length() <= 1) {
return NS_ERROR_INVALID_ARG;
}
if (!aIntermediates.IsEmpty()) {
return NS_ERROR_INVALID_ARG;
}
for (size_t i = 1; i < aCertList.Length() - 1; ++i) {
const auto& cert = aCertList[i];
aIntermediates.AppendElement();
nsTArray<uint8_t>& certBytes = aIntermediates.LastElement();
nsresult rv = cert->GetRawDER(certBytes);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
nsresult nsNSSCertificate::GetRootCertificate(
/* in */ const nsTArray<RefPtr<nsIX509Cert>>& aCertList,
/* out */ nsCOMPtr<nsIX509Cert>& aRoot) {
if (aRoot) {
return NS_ERROR_UNEXPECTED;
}
// If the list is empty, leave aRoot empty.
if (aCertList.IsEmpty()) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509Cert> cert(aCertList.LastElement());
aRoot = cert;
if (!aRoot) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
// NB: Any updates (except disk-only fields) must be kept in sync with
// |SerializeToIPC|.
NS_IMETHODIMP
nsNSSCertificate::Write(nsIObjectOutputStream* aStream) {
NS_ENSURE_STATE(mCert);
// This field used to be the cached EV status, but it is no longer necessary.
nsresult rv = aStream->Write32(0);
if (NS_FAILED(rv)) {
return rv;
}
rv = aStream->Write32(mDER.Length());
rv = aStream->Write32(mCert->derCert.len);
if (NS_FAILED(rv)) {
return rv;
}
return aStream->WriteBytes(Span(mDER));
return aStream->WriteBytes(
AsBytes(Span(mCert->derCert.data, mCert->derCert.len)));
}
// NB: Any updates (except disk-only fields) must be kept in sync with
// |DeserializeFromIPC|.
NS_IMETHODIMP
nsNSSCertificate::Read(nsIObjectInputStream* aStream) {
if (!mDER.IsEmpty() || mCert.isSome()) {
return NS_ERROR_ALREADY_INITIALIZED;
}
NS_ENSURE_STATE(!mCert);
// This field is no longer used.
uint32_t unusedCachedEVStatus;
@ -640,30 +675,35 @@ nsNSSCertificate::Read(nsIObjectInputStream* aStream) {
return rv;
}
rv = aStream->ReadByteArray(len, mDER);
nsCString str;
rv = aStream->ReadBytes(len, getter_Copies(str));
if (NS_FAILED(rv)) {
return rv;
}
if (!InitFromDER(const_cast<char*>(str.get()), len)) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
void nsNSSCertificate::SerializeToIPC(IPC::Message* aMsg) {
bool hasCert = !mDER.IsEmpty();
bool hasCert = static_cast<bool>(mCert);
WriteParam(aMsg, hasCert);
if (!hasCert) {
return;
}
WriteParam(aMsg, mDER);
const nsDependentCSubstring certBytes(
reinterpret_cast<char*>(mCert->derCert.data), mCert->derCert.len);
WriteParam(aMsg, certBytes);
}
bool nsNSSCertificate::DeserializeFromIPC(const IPC::Message* aMsg,
PickleIterator* aIter) {
if (!mDER.IsEmpty() || mCert.isSome()) {
return false;
}
bool hasCert = false;
if (!ReadParam(aMsg, aIter, &hasCert)) {
return false;
@ -673,10 +713,18 @@ bool nsNSSCertificate::DeserializeFromIPC(const IPC::Message* aMsg,
return true;
}
if (!ReadParam(aMsg, aIter, &mDER)) {
nsCString derBytes;
if (!ReadParam(aMsg, aIter, &derBytes)) {
return false;
}
return true;
if (derBytes.Length() == 0) {
return false;
}
// NSS accepts a |char*| here, but doesn't modify the contents of the array
// and casts it back to an |unsigned char*|.
return InitFromDER(const_cast<char*>(derBytes.get()), derBytes.Length());
}
NS_IMETHODIMP

Просмотреть файл

@ -6,15 +6,24 @@
#ifndef nsNSSCertificate_h
#define nsNSSCertificate_h
#include <functional>
#include <vector>
#include "ScopedNSSTypes.h"
#include "certt.h"
#include "mozilla/Maybe.h"
#include "nsCOMPtr.h"
#include "nsIClassInfo.h"
#include "nsISerializable.h"
#include "nsIX509Cert.h"
#include "nsSimpleEnumerator.h"
#include "nsStringFwd.h"
namespace mozilla {
namespace pkix {
class DERArray;
}
} // namespace mozilla
class nsINSSComponent;
class nsNSSCertificate final : public nsIX509Cert,
@ -26,22 +35,45 @@ class nsNSSCertificate final : public nsIX509Cert,
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
nsNSSCertificate();
explicit nsNSSCertificate(CERTCertificate* cert);
explicit nsNSSCertificate(nsTArray<uint8_t>&& der);
nsNSSCertificate();
static nsNSSCertificate* Create(CERTCertificate* cert = nullptr);
static nsNSSCertificate* ConstructFromDER(char* certDER, int derLen);
// This method assumes that the current list object
// is ordered [end entity, intermediates..., root].
// Will return error if used on self-signed or empty chains.
// This method requires that the list `aIntermediates` must be empty.
static nsresult GetIntermediatesAsDER(
/* int */ const nsTArray<RefPtr<nsIX509Cert>>& aCertList,
/* out */ nsTArray<nsTArray<uint8_t>>& aIntermediates);
// Obtain the root certificate of a certificate chain. On an
// empty list, leaves aRoot empty and returns a failure.
// Assumes list is ordered [end entity, intermediates..., root].
static nsresult GetRootCertificate(
const nsTArray<RefPtr<nsIX509Cert>>& aCertList,
/* out */ nsCOMPtr<nsIX509Cert>& aRoot);
private:
virtual ~nsNSSCertificate() = default;
nsTArray<uint8_t> mDER;
mozilla::Maybe<mozilla::UniqueCERTCertificate> mCert;
mozilla::UniqueCERTCertificate mCert;
uint32_t mCertType;
nsresult GetSortableDate(PRTime aTime, nsAString& _aSortableDate);
bool InitFromDER(char* certDER, int derLen); // return false on failure
nsresult GetCertificateHash(nsAString& aFingerprint, SECOidTag aHashAlg);
nsresult InstantiateCert();
};
namespace mozilla {
SECStatus ConstructCERTCertListFromReversedDERArray(
const mozilla::pkix::DERArray& certArray,
/*out*/ mozilla::UniqueCERTCertList& certList);
} // namespace mozilla
#define NS_X509CERT_CID \
{ /* 660a3226-915c-4ffb-bb20-8985a632df05 */ \
0x660a3226, 0x915c, 0x4ffb, { \

Просмотреть файл

@ -79,7 +79,10 @@ nsNSSCertificateDB::FindCertByDBKey(const nsACString& aDBKey,
if (!cert) {
return NS_OK;
}
nsCOMPtr<nsIX509Cert> nssCert = new nsNSSCertificate(cert.get());
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
if (!nssCert) {
return NS_ERROR_OUT_OF_MEMORY;
}
nssCert.forget(_cert);
return NS_OK;
}
@ -384,7 +387,10 @@ nsresult nsNSSCertificateDB::ConstructCertArrayFromUniqueCertList(
for (CERTCertListNode* node = CERT_LIST_HEAD(aCertListIn.get());
!CERT_LIST_END(node, aCertListIn.get()); node = CERT_LIST_NEXT(node)) {
RefPtr<nsIX509Cert> cert = new nsNSSCertificate(node->cert);
RefPtr<nsIX509Cert> cert = nsNSSCertificate::Create(node->cert);
if (!cert) {
return NS_ERROR_OUT_OF_MEMORY;
}
aCertListOut.AppendElement(cert);
}
return NS_OK;
@ -400,6 +406,7 @@ nsNSSCertificateDB::ImportCertificates(uint8_t* data, uint32_t length,
}
nsTArray<nsTArray<uint8_t>> certsArray;
nsresult rv = getCertsFromPackage(certsArray, data, length);
if (NS_FAILED(rv)) {
return rv;
@ -412,7 +419,11 @@ nsNSSCertificateDB::ImportCertificates(uint8_t* data, uint32_t length,
// Now let's create some certs to work with
for (nsTArray<uint8_t>& certDER : certsArray) {
nsCOMPtr<nsIX509Cert> cert = new nsNSSCertificate(std::move(certDER));
nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::ConstructFromDER(
BitwiseCast<char*, uint8_t*>(certDER.Elements()), certDER.Length());
if (!cert) {
return NS_ERROR_FAILURE;
}
nsresult rv = array->AppendElement(cert);
if (NS_FAILED(rv)) {
return rv;
@ -557,7 +568,7 @@ nsNSSCertificateDB::ImportUserCertificate(uint8_t* data, uint32_t length,
UniquePK11SlotInfo slot(PK11_KeyForCertExists(cert.get(), nullptr, ctx));
if (!slot) {
nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(cert.get());
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert.get());
DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow);
return NS_ERROR_FAILURE;
}
@ -579,7 +590,7 @@ nsNSSCertificateDB::ImportUserCertificate(uint8_t* data, uint32_t length,
slot = nullptr;
{
nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(cert.get());
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert.get());
DisplayCertificateAlert(ctx, "UserCertImported", certToShow);
}
@ -879,7 +890,10 @@ nsresult nsNSSCertificateDB::ConstructX509FromSpan(
return (PORT_GetError() == SEC_ERROR_NO_MEMORY) ? NS_ERROR_OUT_OF_MEMORY
: NS_ERROR_FAILURE;
nsCOMPtr<nsIX509Cert> nssCert = new nsNSSCertificate(cert.get());
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
if (!nssCert) {
return NS_ERROR_OUT_OF_MEMORY;
}
nssCert.forget(_retval);
return NS_OK;
}
@ -1281,8 +1295,13 @@ nsresult VerifyCertAtTime(nsIX509Cert* aCert,
}
if (result == mozilla::pkix::Success) {
for (auto& certDER : resultChain) {
RefPtr<nsIX509Cert> cert = new nsNSSCertificate(std::move(certDER));
for (const auto& certDER : resultChain) {
RefPtr<nsIX509Cert> cert = nsNSSCertificate::ConstructFromDER(
const_cast<char*>(reinterpret_cast<const char*>(certDER.Elements())),
static_cast<int>(certDER.Length()));
if (!cert) {
return NS_ERROR_FAILURE;
}
aVerifiedChain.AppendElement(cert);
}

Просмотреть файл

@ -2518,7 +2518,10 @@ nsNSSComponent::IsCertTestBuiltInRoot(CERTCertificate* cert, bool* result) {
*result = false;
#ifdef DEBUG
RefPtr<nsNSSCertificate> nsc = new nsNSSCertificate(cert);
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert);
if (!nsc) {
return NS_ERROR_FAILURE;
}
nsAutoString certHash;
nsresult rv = nsc->GetSha256Fingerprint(certHash);
if (NS_FAILED(rv)) {

Просмотреть файл

@ -2236,30 +2236,11 @@ mozilla::pkix::Result ClientAuthCertNonverifyingTrustDomain::FindIssuer(
}
mozilla::pkix::Result ClientAuthCertNonverifyingTrustDomain::IsChainValid(
const DERArray& certArray, Time, const CertPolicyId&) {
mBuiltChain = UniqueCERTCertList(CERT_NewCertList());
if (!mBuiltChain) {
const DERArray& certChain, Time, const CertPolicyId&) {
if (ConstructCERTCertListFromReversedDERArray(certChain, mBuiltChain) !=
SECSuccess) {
return MapPRErrorCodeToResult(PR_GetError());
}
CERTCertDBHandle* certDB(CERT_GetDefaultCertDB()); // non-owning
size_t numCerts = certArray.GetLength();
for (size_t i = 0; i < numCerts; ++i) {
SECItem certDER(UnsafeMapInputToSECItem(*certArray.GetDER(i)));
UniqueCERTCertificate cert(
CERT_NewTempCertificate(certDB, &certDER, nullptr, false, true));
if (!cert) {
return MapPRErrorCodeToResult(PR_GetError());
}
// certArray is ordered with the root first, but we want the resulting
// certList to have the root last.
if (CERT_AddCertToListHead(mBuiltChain.get(), cert.get()) != SECSuccess) {
return MapPRErrorCodeToResult(PR_GetError());
}
Unused << cert.release(); // cert is now owned by mBuiltChain.
}
return Success;
}
@ -2413,7 +2394,7 @@ void ClientAuthDataRunnable::RunOnTargetThread() {
if (cars) {
nsCString rememberedDBKey;
bool found;
nsCOMPtr<nsIX509Cert> cert(new nsNSSCertificate(mServerCert));
nsCOMPtr<nsIX509Cert> cert(nsNSSCertificate::Create(mServerCert));
nsresult rv = cars->HasRememberedDecision(
hostname, mInfo.OriginAttributesRef(), cert, rememberedDBKey, &found);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -2465,7 +2446,10 @@ void ClientAuthDataRunnable::RunOnTargetThread() {
for (CERTCertListNode* node = CERT_LIST_HEAD(certList);
!CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node)) {
nsCOMPtr<nsIX509Cert> tempCert = new nsNSSCertificate(node->cert);
nsCOMPtr<nsIX509Cert> tempCert = nsNSSCertificate::Create(node->cert);
if (NS_WARN_IF(!tempCert)) {
return;
}
nsresult rv = certArray->AppendElement(tempCert);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
@ -2506,10 +2490,10 @@ void ClientAuthDataRunnable::RunOnTargetThread() {
}
if (cars && wantRemember) {
nsCOMPtr<nsIX509Cert> serverCert(new nsNSSCertificate(mServerCert));
nsCOMPtr<nsIX509Cert> serverCert(nsNSSCertificate::Create(mServerCert));
nsCOMPtr<nsIX509Cert> clientCert;
if (certChosen) {
clientCert = new nsNSSCertificate(mSelectedCertificate.get());
clientCert = nsNSSCertificate::Create(mSelectedCertificate.get());
}
rv = cars->RememberDecision(hostname, mInfo.OriginAttributesRef(),
serverCert, clientCert);

Просмотреть файл

@ -0,0 +1,412 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "gtest/gtest.h"
#include "nsCOMPtr.h"
#include "nsIPrefService.h"
#include "nsIX509Cert.h"
#include "nsIX509CertDB.h"
#include "nsNSSCertificate.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
// certspec (for pycert.py)
//
// issuer:ca
// subject:ca
// extension:basicConstraints:cA,
// extension:keyUsage:cRLSign,keyCertSign
// serialNumber:1
const char* kCaPem =
"-----BEGIN CERTIFICATE-----\n"
"MIICsjCCAZygAwIBAgIBATALBgkqhkiG9w0BAQswDTELMAkGA1UEAwwCY2EwIhgP\n"
"MjAxNTExMjgwMDAwMDBaGA8yMDE4MDIwNTAwMDAwMFowDTELMAkGA1UEAwwCY2Ew\n"
"ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQ\n"
"PTwT2erkNUq07PVoV2wke8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH\n"
"9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw\n"
"4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86\n"
"exCABiTMHGyXrZZhW7filhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0\n"
"ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2N\n"
"AgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMAsGCSqGSIb3DQEB\n"
"CwOCAQEAchHf1yV+blE6fvS53L3DGmvxEpn9+t+xwOvWczBmLFEzUPdncakdaWlQ\n"
"v7q81BPyjBqkYbQi15Ws81hY3dnXn8LT1QktCL9guvc3z4fMdQbRjpjcIReCYt3E\n"
"PB22Jl2FCm6ii4XL0qDFD26WK3zMe2Uks6t55f8VeDTBGNoPp2JMsWY1Pi4vR6wK\n"
"AY96WoXS/qrYkmMEOgFu907pApeAeE8VJzXjqMLF6/W1VN7ISnGzWQ8zKQnlp3YA\n"
"mvWZQcD6INK8mvpZxIeu6NtHaKEXGw7tlGekmkVhapPtQZYnWcsXybRrZf5g3hOh\n"
"JFPl8kW42VoxXL11PP5NX2ylTsJ//g==\n"
"-----END CERTIFICATE-----";
// certspec (for pycert.py)
//
// issuer:ca
// subject:ca-intermediate
// extension:basicConstraints:cA,
// extension:keyUsage:cRLSign,keyCertSign
// serialNumber:2
const char* kCaIntermediatePem =
"-----BEGIN CERTIFICATE-----\n"
"MIICvzCCAamgAwIBAgIBAjALBgkqhkiG9w0BAQswDTELMAkGA1UEAwwCY2EwIhgP\n"
"MjAxNTExMjgwMDAwMDBaGA8yMDE4MDIwNTAwMDAwMFowGjEYMBYGA1UEAwwPY2Et\n"
"aW50ZXJtZWRpYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohR\n"
"qESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+Kv\n"
"WnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+\n"
"rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgfqDfTiEPv\n"
"JxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/ytHSXTCe+5\n"
"Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6\n"
"clHEMdUDrNoYCjXtjQIDAQABox0wGzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB\n"
"BjALBgkqhkiG9w0BAQsDggEBAC0ys8UOmYgvH5rrTeV6u79ocHqdQFwdmR7/4d08\n"
"i3asC7b70dw0ehA5vi4cq5mwBvQOGZq4wvsR4jSJW0+0hjWL1dr2M6VxmCfjdqhU\n"
"NQHPlY6y7lLfYQbFfUHX99ZgygJjdmmm7H8MBP4UgPb8jl6Xq53FgYykiX/qPmfb\n"
"pzpOFHDi+Tk67DLCvPz03UUDYNx1H0OhRimj0DWhdYGUg2DHfLQkOEYvrYG4wYB8\n"
"AB/0hrG51yFsuXrzhYcinTKby11Qk6PjnOQ/aZvK00Jffep/RHs8lIOWty9SarMG\n"
"oNSECn+6I9AgStJdo6LuP1QPyrQe3DZtAHhRJAPAoU7BSqM=\n"
"-----END CERTIFICATE-----";
const uint8_t kCaIntermediateDer[] = {
0x30, 0x82, 0x02, 0xBF, 0x30, 0x82, 0x01, 0xA9, 0xA0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x01, 0x02, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x30, 0x0D, 0x31, 0x0B, 0x30, 0x09, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x02, 0x63, 0x61, 0x30, 0x22, 0x18, 0x0F,
0x32, 0x30, 0x31, 0x35, 0x31, 0x31, 0x32, 0x38, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x32, 0x30,
0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x1A, 0x31, 0x18,
0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x63, 0x61, 0x2D,
0x69, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65,
0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00,
0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBA, 0x88, 0x51,
0xA8, 0x44, 0x8E, 0x16, 0xD6, 0x41, 0xFD, 0x6E, 0xB6, 0x88, 0x06, 0x36,
0x10, 0x3D, 0x3C, 0x13, 0xD9, 0xEA, 0xE4, 0x35, 0x4A, 0xB4, 0xEC, 0xF5,
0x68, 0x57, 0x6C, 0x24, 0x7B, 0xC1, 0xC7, 0x25, 0xA8, 0xE0, 0xD8, 0x1F,
0xBD, 0xB1, 0x9C, 0x06, 0x9B, 0x6E, 0x1A, 0x86, 0xF2, 0x6B, 0xE2, 0xAF,
0x5A, 0x75, 0x6B, 0x6A, 0x64, 0x71, 0x08, 0x7A, 0xA5, 0x5A, 0xA7, 0x45,
0x87, 0xF7, 0x1C, 0xD5, 0x24, 0x9C, 0x02, 0x7E, 0xCD, 0x43, 0xFC, 0x1E,
0x69, 0xD0, 0x38, 0x20, 0x29, 0x93, 0xAB, 0x20, 0xC3, 0x49, 0xE4, 0xDB,
0xB9, 0x4C, 0xC2, 0x6B, 0x6C, 0x0E, 0xED, 0x15, 0x82, 0x0F, 0xF1, 0x7E,
0xAD, 0x69, 0x1A, 0xB1, 0xD3, 0x02, 0x3A, 0x8B, 0x2A, 0x41, 0xEE, 0xA7,
0x70, 0xE0, 0x0F, 0x0D, 0x8D, 0xFD, 0x66, 0x0B, 0x2B, 0xB0, 0x24, 0x92,
0xA4, 0x7D, 0xB9, 0x88, 0x61, 0x79, 0x90, 0xB1, 0x57, 0x90, 0x3D, 0xD2,
0x3B, 0xC5, 0xE0, 0xB8, 0x48, 0x1F, 0xA8, 0x37, 0xD3, 0x88, 0x43, 0xEF,
0x27, 0x16, 0xD8, 0x55, 0xB7, 0x66, 0x5A, 0xAA, 0x7E, 0x02, 0x90, 0x2F,
0x3A, 0x7B, 0x10, 0x80, 0x06, 0x24, 0xCC, 0x1C, 0x6C, 0x97, 0xAD, 0x96,
0x61, 0x5B, 0xB7, 0xE2, 0x96, 0x12, 0xC0, 0x75, 0x31, 0xA3, 0x0C, 0x91,
0xDD, 0xB4, 0xCA, 0xF7, 0xFC, 0xAD, 0x1D, 0x25, 0xD3, 0x09, 0xEF, 0xB9,
0x17, 0x0E, 0xA7, 0x68, 0xE1, 0xB3, 0x7B, 0x2F, 0x22, 0x6F, 0x69, 0xE3,
0xB4, 0x8A, 0x95, 0x61, 0x1D, 0xEE, 0x26, 0xD6, 0x25, 0x9D, 0xAB, 0x91,
0x08, 0x4E, 0x36, 0xCB, 0x1C, 0x24, 0x04, 0x2C, 0xBF, 0x16, 0x8B, 0x2F,
0xE5, 0xF1, 0x8F, 0x99, 0x17, 0x31, 0xB8, 0xB3, 0xFE, 0x49, 0x23, 0xFA,
0x72, 0x51, 0xC4, 0x31, 0xD5, 0x03, 0xAC, 0xDA, 0x18, 0x0A, 0x35, 0xED,
0x8D, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x1D, 0x30, 0x1B, 0x30, 0x0C,
0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF,
0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01,
0x06, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
0x01, 0x0B, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2D, 0x32, 0xB3, 0xC5, 0x0E,
0x99, 0x88, 0x2F, 0x1F, 0x9A, 0xEB, 0x4D, 0xE5, 0x7A, 0xBB, 0xBF, 0x68,
0x70, 0x7A, 0x9D, 0x40, 0x5C, 0x1D, 0x99, 0x1E, 0xFF, 0xE1, 0xDD, 0x3C,
0x8B, 0x76, 0xAC, 0x0B, 0xB6, 0xFB, 0xD1, 0xDC, 0x34, 0x7A, 0x10, 0x39,
0xBE, 0x2E, 0x1C, 0xAB, 0x99, 0xB0, 0x06, 0xF4, 0x0E, 0x19, 0x9A, 0xB8,
0xC2, 0xFB, 0x11, 0xE2, 0x34, 0x89, 0x5B, 0x4F, 0xB4, 0x86, 0x35, 0x8B,
0xD5, 0xDA, 0xF6, 0x33, 0xA5, 0x71, 0x98, 0x27, 0xE3, 0x76, 0xA8, 0x54,
0x35, 0x01, 0xCF, 0x95, 0x8E, 0xB2, 0xEE, 0x52, 0xDF, 0x61, 0x06, 0xC5,
0x7D, 0x41, 0xD7, 0xF7, 0xD6, 0x60, 0xCA, 0x02, 0x63, 0x76, 0x69, 0xA6,
0xEC, 0x7F, 0x0C, 0x04, 0xFE, 0x14, 0x80, 0xF6, 0xFC, 0x8E, 0x5E, 0x97,
0xAB, 0x9D, 0xC5, 0x81, 0x8C, 0xA4, 0x89, 0x7F, 0xEA, 0x3E, 0x67, 0xDB,
0xA7, 0x3A, 0x4E, 0x14, 0x70, 0xE2, 0xF9, 0x39, 0x3A, 0xEC, 0x32, 0xC2,
0xBC, 0xFC, 0xF4, 0xDD, 0x45, 0x03, 0x60, 0xDC, 0x75, 0x1F, 0x43, 0xA1,
0x46, 0x29, 0xA3, 0xD0, 0x35, 0xA1, 0x75, 0x81, 0x94, 0x83, 0x60, 0xC7,
0x7C, 0xB4, 0x24, 0x38, 0x46, 0x2F, 0xAD, 0x81, 0xB8, 0xC1, 0x80, 0x7C,
0x00, 0x1F, 0xF4, 0x86, 0xB1, 0xB9, 0xD7, 0x21, 0x6C, 0xB9, 0x7A, 0xF3,
0x85, 0x87, 0x22, 0x9D, 0x32, 0x9B, 0xCB, 0x5D, 0x50, 0x93, 0xA3, 0xE3,
0x9C, 0xE4, 0x3F, 0x69, 0x9B, 0xCA, 0xD3, 0x42, 0x5F, 0x7D, 0xEA, 0x7F,
0x44, 0x7B, 0x3C, 0x94, 0x83, 0x96, 0xB7, 0x2F, 0x52, 0x6A, 0xB3, 0x06,
0xA0, 0xD4, 0x84, 0x0A, 0x7F, 0xBA, 0x23, 0xD0, 0x20, 0x4A, 0xD2, 0x5D,
0xA3, 0xA2, 0xEE, 0x3F, 0x54, 0x0F, 0xCA, 0xB4, 0x1E, 0xDC, 0x36, 0x6D,
0x00, 0x78, 0x51, 0x24, 0x03, 0xC0, 0xA1, 0x4E, 0xC1, 0x4A, 0xA3};
// certspec (for pycert.py)
//
// issuer:ca-intermediate
// subject:ca-second-intermediate
// extension:basicConstraints:cA,
// extension:keyUsage:cRLSign,keyCertSign
// serialNumber:3
const char* kCaSecondIntermediatePem =
"-----BEGIN CERTIFICATE-----\n"
"MIIC0zCCAb2gAwIBAgIBAzALBgkqhkiG9w0BAQswGjEYMBYGA1UEAwwPY2EtaW50\n"
"ZXJtZWRpYXRlMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAwMDBaMCEx\n"
"HzAdBgNVBAMMFmNhLXNlY29uZC1pbnRlcm1lZGlhdGUwggEiMA0GCSqGSIb3DQEB\n"
"AQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wk\n"
"e8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0Dgg\n"
"KZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmI\n"
"YXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7fi\n"
"lhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbL\n"
"HCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAGjHTAbMAwGA1Ud\n"
"EwQFMAMBAf8wCwYDVR0PBAQDAgEGMAsGCSqGSIb3DQEBCwOCAQEAaK6K7/0Y+PkG\n"
"MQJjumTlt6XUQjQ3Y6zuSOMlZ1wmJoBqWabYhJ4qXfcSMQiw+kZ+mQTFk+IdurGC\n"
"RHrAKwDGNRqmjnQ56qjwHNTTxhJozP09vBCgs3fIQQY/Nq/uISoQvOZmoIriFZf6\n"
"8czHMlj1vIC6zp4XHWdqkQ7aF4YFsTfM0kBPrm0Y6Nn0VKzWNdmaIs/X5OcR6ZAG\n"
"zGN9UZV+ZftcfdqI0XSVCVRAK5MeEa+twLr5PE/Nl7/Ig/tUJMWGSbcrWRZQTXQu\n"
"Rx7CSKcoatyMhJOd2YT4BvoijEJCxTKWMJzFe2uZAphQHUlVmE9IbUQM0T1N6RNd\n"
"1dH4o4UeuQ==\n"
"-----END CERTIFICATE-----";
const uint8_t kCaSecondIntermediateDer[] = {
0x30, 0x82, 0x02, 0xD3, 0x30, 0x82, 0x01, 0xBD, 0xA0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x01, 0x03, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x30, 0x1A, 0x31, 0x18, 0x30, 0x16, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x63, 0x61, 0x2D, 0x69, 0x6E, 0x74,
0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x30, 0x22, 0x18,
0x0F, 0x32, 0x30, 0x31, 0x35, 0x31, 0x31, 0x32, 0x38, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x32,
0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x21, 0x31,
0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x63, 0x61,
0x2D, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x2D, 0x69, 0x6E, 0x74, 0x65,
0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x30, 0x82, 0x01, 0x22,
0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A,
0x02, 0x82, 0x01, 0x01, 0x00, 0xBA, 0x88, 0x51, 0xA8, 0x44, 0x8E, 0x16,
0xD6, 0x41, 0xFD, 0x6E, 0xB6, 0x88, 0x06, 0x36, 0x10, 0x3D, 0x3C, 0x13,
0xD9, 0xEA, 0xE4, 0x35, 0x4A, 0xB4, 0xEC, 0xF5, 0x68, 0x57, 0x6C, 0x24,
0x7B, 0xC1, 0xC7, 0x25, 0xA8, 0xE0, 0xD8, 0x1F, 0xBD, 0xB1, 0x9C, 0x06,
0x9B, 0x6E, 0x1A, 0x86, 0xF2, 0x6B, 0xE2, 0xAF, 0x5A, 0x75, 0x6B, 0x6A,
0x64, 0x71, 0x08, 0x7A, 0xA5, 0x5A, 0xA7, 0x45, 0x87, 0xF7, 0x1C, 0xD5,
0x24, 0x9C, 0x02, 0x7E, 0xCD, 0x43, 0xFC, 0x1E, 0x69, 0xD0, 0x38, 0x20,
0x29, 0x93, 0xAB, 0x20, 0xC3, 0x49, 0xE4, 0xDB, 0xB9, 0x4C, 0xC2, 0x6B,
0x6C, 0x0E, 0xED, 0x15, 0x82, 0x0F, 0xF1, 0x7E, 0xAD, 0x69, 0x1A, 0xB1,
0xD3, 0x02, 0x3A, 0x8B, 0x2A, 0x41, 0xEE, 0xA7, 0x70, 0xE0, 0x0F, 0x0D,
0x8D, 0xFD, 0x66, 0x0B, 0x2B, 0xB0, 0x24, 0x92, 0xA4, 0x7D, 0xB9, 0x88,
0x61, 0x79, 0x90, 0xB1, 0x57, 0x90, 0x3D, 0xD2, 0x3B, 0xC5, 0xE0, 0xB8,
0x48, 0x1F, 0xA8, 0x37, 0xD3, 0x88, 0x43, 0xEF, 0x27, 0x16, 0xD8, 0x55,
0xB7, 0x66, 0x5A, 0xAA, 0x7E, 0x02, 0x90, 0x2F, 0x3A, 0x7B, 0x10, 0x80,
0x06, 0x24, 0xCC, 0x1C, 0x6C, 0x97, 0xAD, 0x96, 0x61, 0x5B, 0xB7, 0xE2,
0x96, 0x12, 0xC0, 0x75, 0x31, 0xA3, 0x0C, 0x91, 0xDD, 0xB4, 0xCA, 0xF7,
0xFC, 0xAD, 0x1D, 0x25, 0xD3, 0x09, 0xEF, 0xB9, 0x17, 0x0E, 0xA7, 0x68,
0xE1, 0xB3, 0x7B, 0x2F, 0x22, 0x6F, 0x69, 0xE3, 0xB4, 0x8A, 0x95, 0x61,
0x1D, 0xEE, 0x26, 0xD6, 0x25, 0x9D, 0xAB, 0x91, 0x08, 0x4E, 0x36, 0xCB,
0x1C, 0x24, 0x04, 0x2C, 0xBF, 0x16, 0x8B, 0x2F, 0xE5, 0xF1, 0x8F, 0x99,
0x17, 0x31, 0xB8, 0xB3, 0xFE, 0x49, 0x23, 0xFA, 0x72, 0x51, 0xC4, 0x31,
0xD5, 0x03, 0xAC, 0xDA, 0x18, 0x0A, 0x35, 0xED, 0x8D, 0x02, 0x03, 0x01,
0x00, 0x01, 0xA3, 0x1D, 0x30, 0x1B, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D,
0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0B, 0x06, 0x03,
0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0B, 0x06,
0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x03, 0x82,
0x01, 0x01, 0x00, 0x68, 0xAE, 0x8A, 0xEF, 0xFD, 0x18, 0xF8, 0xF9, 0x06,
0x31, 0x02, 0x63, 0xBA, 0x64, 0xE5, 0xB7, 0xA5, 0xD4, 0x42, 0x34, 0x37,
0x63, 0xAC, 0xEE, 0x48, 0xE3, 0x25, 0x67, 0x5C, 0x26, 0x26, 0x80, 0x6A,
0x59, 0xA6, 0xD8, 0x84, 0x9E, 0x2A, 0x5D, 0xF7, 0x12, 0x31, 0x08, 0xB0,
0xFA, 0x46, 0x7E, 0x99, 0x04, 0xC5, 0x93, 0xE2, 0x1D, 0xBA, 0xB1, 0x82,
0x44, 0x7A, 0xC0, 0x2B, 0x00, 0xC6, 0x35, 0x1A, 0xA6, 0x8E, 0x74, 0x39,
0xEA, 0xA8, 0xF0, 0x1C, 0xD4, 0xD3, 0xC6, 0x12, 0x68, 0xCC, 0xFD, 0x3D,
0xBC, 0x10, 0xA0, 0xB3, 0x77, 0xC8, 0x41, 0x06, 0x3F, 0x36, 0xAF, 0xEE,
0x21, 0x2A, 0x10, 0xBC, 0xE6, 0x66, 0xA0, 0x8A, 0xE2, 0x15, 0x97, 0xFA,
0xF1, 0xCC, 0xC7, 0x32, 0x58, 0xF5, 0xBC, 0x80, 0xBA, 0xCE, 0x9E, 0x17,
0x1D, 0x67, 0x6A, 0x91, 0x0E, 0xDA, 0x17, 0x86, 0x05, 0xB1, 0x37, 0xCC,
0xD2, 0x40, 0x4F, 0xAE, 0x6D, 0x18, 0xE8, 0xD9, 0xF4, 0x54, 0xAC, 0xD6,
0x35, 0xD9, 0x9A, 0x22, 0xCF, 0xD7, 0xE4, 0xE7, 0x11, 0xE9, 0x90, 0x06,
0xCC, 0x63, 0x7D, 0x51, 0x95, 0x7E, 0x65, 0xFB, 0x5C, 0x7D, 0xDA, 0x88,
0xD1, 0x74, 0x95, 0x09, 0x54, 0x40, 0x2B, 0x93, 0x1E, 0x11, 0xAF, 0xAD,
0xC0, 0xBA, 0xF9, 0x3C, 0x4F, 0xCD, 0x97, 0xBF, 0xC8, 0x83, 0xFB, 0x54,
0x24, 0xC5, 0x86, 0x49, 0xB7, 0x2B, 0x59, 0x16, 0x50, 0x4D, 0x74, 0x2E,
0x47, 0x1E, 0xC2, 0x48, 0xA7, 0x28, 0x6A, 0xDC, 0x8C, 0x84, 0x93, 0x9D,
0xD9, 0x84, 0xF8, 0x06, 0xFA, 0x22, 0x8C, 0x42, 0x42, 0xC5, 0x32, 0x96,
0x30, 0x9C, 0xC5, 0x7B, 0x6B, 0x99, 0x02, 0x98, 0x50, 0x1D, 0x49, 0x55,
0x98, 0x4F, 0x48, 0x6D, 0x44, 0x0C, 0xD1, 0x3D, 0x4D, 0xE9, 0x13, 0x5D,
0xD5, 0xD1, 0xF8, 0xA3, 0x85, 0x1E, 0xB9};
// certspec (for pycert.py)
//
// issuer:ca-second-intermediate
// subject:ee
const char* kEePem =
"-----BEGIN CERTIFICATE-----\n"
"MIICujCCAaSgAwIBAgIUMy8NE67P/4jkaCra7rOVVvX4+GswCwYJKoZIhvcNAQEL\n"
"MCExHzAdBgNVBAMMFmNhLXNlY29uZC1pbnRlcm1lZGlhdGUwIhgPMjAxNTExMjgw\n"
"MDAwMDBaGA8yMDE4MDIwNTAwMDAwMFowDTELMAkGA1UEAwwCZWUwggEiMA0GCSqG\n"
"SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq0\n"
"7PVoV2wke8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D\n"
"/B5p0DggKZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuw\n"
"JJKkfbmIYXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyX\n"
"rZZhW7filhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWd\n"
"q5EITjbLHCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAEwCwYJ\n"
"KoZIhvcNAQELA4IBAQCE5V5YiFPtbb1dOCIMGC5X/6kfQkQmIfvEZIol0MRXmP4g\n"
"CsOPbTI+BNxYVNk5RHIlr+6e0d8TNiABem4FZK3kea4ugN8ez3IsK7ug7qdrooNA\n"
"MiHOvrLmAw2nQWexdDRf7OPeVj03BwELzGTOGPjAqDktTsK57OfXyFTm9nl75WQo\n"
"+EWX+CdV4L1o2rgABvSiMnMdycftCC73Hr/3ypADqY7nDrKpxYdrGgzAQvx3DjPv\n"
"b7nBKH/gXg3kzoWpeQmJYPl9Vd+DvGljS5i71oLbvCwlDX7ZswGcvb8pQ7Tni5HA\n"
"VYpAYLokxIDFnyVT9oCACJuJ5LvpBBrhd0+1uUPE\n"
"-----END CERTIFICATE-----";
class psm_CertList : public ::testing::Test {
protected:
void SetUp() override {
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
ASSERT_TRUE(prefs)
<< "couldn't get nsIPrefBranch";
// When PSM initializes, it attempts to get some localized strings.
// As a result, Android flips out if this isn't set.
nsresult rv = prefs->SetBoolPref("intl.locale.matchOS", true);
ASSERT_TRUE(NS_SUCCEEDED(rv))
<< "couldn't set pref 'intl.locale.matchOS'";
nsCOMPtr<nsIX509CertDB> certdb(do_GetService(NS_X509CERTDB_CONTRACTID));
ASSERT_TRUE(certdb)
<< "couldn't get certdb";
}
};
static nsresult AddCertFromStringToList(
const char* aPem, nsTArray<RefPtr<nsIX509Cert>>& aCertList) {
RefPtr<nsIX509Cert> cert;
cert =
nsNSSCertificate::ConstructFromDER(const_cast<char*>(aPem), strlen(aPem));
if (!cert) {
return NS_ERROR_FAILURE;
}
aCertList.AppendElement(cert);
return NS_OK;
}
TEST_F(psm_CertList, TestInvalidSegmenting) {
nsTArray<RefPtr<nsIX509Cert>> certList;
nsTArray<nsTArray<uint8_t>> intCerts;
nsresult rv = nsNSSCertificate::GetIntermediatesAsDER(certList, intCerts);
ASSERT_EQ(rv, NS_ERROR_INVALID_ARG) << "Empty lists can't be segmented";
rv = AddCertFromStringToList(kCaPem, certList);
ASSERT_EQ(rv, NS_OK) << "Should have loaded OK";
intCerts.Clear();
rv = nsNSSCertificate::GetIntermediatesAsDER(certList, intCerts);
ASSERT_EQ(rv, NS_ERROR_INVALID_ARG) << "Lists of one can't be segmented";
}
TEST_F(psm_CertList, TestValidSegmenting) {
nsTArray<RefPtr<nsIX509Cert>> certList;
nsresult rv = AddCertFromStringToList(kEePem, certList);
ASSERT_EQ(rv, NS_OK) << "Should have loaded OK";
rv = AddCertFromStringToList(kCaSecondIntermediatePem, certList);
ASSERT_EQ(rv, NS_OK) << "Should have loaded OK";
nsTArray<nsTArray<uint8_t>> intCerts;
rv = nsNSSCertificate::GetIntermediatesAsDER(certList, intCerts);
ASSERT_EQ(rv, NS_OK) << "Should have segmented OK";
ASSERT_EQ(intCerts.Length(), static_cast<size_t>(0))
<< "There should be no intermediates";
rv = AddCertFromStringToList(kCaIntermediatePem, certList);
ASSERT_EQ(rv, NS_OK) << "Should have loaded OK";
intCerts.Clear();
rv = nsNSSCertificate::GetIntermediatesAsDER(certList, intCerts);
ASSERT_EQ(rv, NS_OK) << "Should have segmented OK";
ASSERT_EQ(intCerts.Length(), static_cast<size_t>(1))
<< "There should be one intermediate";
rv = AddCertFromStringToList(kCaPem, certList);
ASSERT_EQ(rv, NS_OK) << "Should have loaded OK";
intCerts.Clear();
rv = nsNSSCertificate::GetIntermediatesAsDER(certList, intCerts);
ASSERT_EQ(rv, NS_OK) << "Should have segmented OK";
ASSERT_EQ(intCerts.Length(), static_cast<size_t>(2))
<< "There should be two intermediates";
const nsTArray<uint8_t> secondIntermediateBinaryArray(
kCaSecondIntermediateDer, sizeof(kCaSecondIntermediateDer));
const nsTArray<uint8_t> intermediateBinaryArray(kCaIntermediateDer,
sizeof(kCaIntermediateDer));
for (size_t i = 0; i < intCerts.Length(); ++i) {
const nsTArray<uint8_t>& certArray = intCerts[i];
if (i < intCerts.Length() - 1) {
if (certArray != secondIntermediateBinaryArray) {
rv = NS_ERROR_FAILURE;
break;
}
} else {
if (certArray != intermediateBinaryArray) {
rv = NS_ERROR_FAILURE;
break;
}
}
}
ASSERT_EQ(rv, NS_OK) << "Should have looped OK.";
}
TEST_F(psm_CertList, TestGetRootCertificateChainTwo) {
nsTArray<RefPtr<nsIX509Cert>> certList;
nsresult rv = AddCertFromStringToList(kCaIntermediatePem, certList);
ASSERT_EQ(NS_OK, rv) << "Should have loaded OK";
rv = AddCertFromStringToList(kCaPem, certList);
ASSERT_EQ(NS_OK, rv) << "Should have loaded OK";
nsCOMPtr<nsIX509Cert> rootCert;
rv = nsNSSCertificate::GetRootCertificate(certList, rootCert);
EXPECT_EQ(NS_OK, rv) << "Should have fetched the root OK";
ASSERT_TRUE(rootCert)
<< "Root cert should be filled in";
nsAutoString rootCn;
EXPECT_TRUE(NS_SUCCEEDED(rootCert->GetCommonName(rootCn)))
<< "Getters should work.";
EXPECT_TRUE(rootCn.EqualsLiteral("ca")) << "Root CN should match";
// Re-fetch and ensure we get the same certificate.
nsCOMPtr<nsIX509Cert> rootCertRepeat;
rv = nsNSSCertificate::GetRootCertificate(certList, rootCertRepeat);
EXPECT_EQ(NS_OK, rv) << "Should have fetched the root OK the second time";
ASSERT_TRUE(rootCertRepeat)
<< "Root cert should still be filled in";
nsAutoString rootRepeatCn;
EXPECT_TRUE(NS_SUCCEEDED(rootCertRepeat->GetCommonName(rootRepeatCn)))
<< "Getters should work.";
EXPECT_TRUE(rootRepeatCn.EqualsLiteral("ca")) << "Root CN should still match";
}
TEST_F(psm_CertList, TestGetRootCertificateChainFour) {
nsTArray<RefPtr<nsIX509Cert>> certList;
nsresult rv = AddCertFromStringToList(kEePem, certList);
ASSERT_EQ(NS_OK, rv) << "Should have loaded OK";
rv = AddCertFromStringToList(kCaSecondIntermediatePem, certList);
ASSERT_EQ(NS_OK, rv) << "Should have loaded OK";
rv = AddCertFromStringToList(kCaIntermediatePem, certList);
ASSERT_EQ(NS_OK, rv) << "Should have loaded OK";
rv = AddCertFromStringToList(kCaPem, certList);
ASSERT_EQ(NS_OK, rv) << "Should have loaded OK";
nsCOMPtr<nsIX509Cert> rootCert;
rv = nsNSSCertificate::GetRootCertificate(certList, rootCert);
EXPECT_EQ(NS_OK, rv) << "Should have again fetched the root OK";
ASSERT_TRUE(rootCert)
<< "Root cert should be filled in";
nsAutoString rootCn;
EXPECT_TRUE(NS_SUCCEEDED(rootCert->GetCommonName(rootCn)))
<< "Getters should work.";
EXPECT_TRUE(rootCn.EqualsLiteral("ca")) << "Root CN should match";
}
TEST_F(psm_CertList, TestGetRootCertificateChainEmpty) {
nsTArray<RefPtr<nsIX509Cert>> certList;
nsCOMPtr<nsIX509Cert> rootCert;
nsresult rv = nsNSSCertificate::GetRootCertificate(certList, rootCert);
EXPECT_EQ(NS_ERROR_FAILURE, rv)
<< "Should have returned NS_ERROR_FAILURE because certList was empty";
EXPECT_FALSE(rootCert) << "Root cert should be empty";
}

Просмотреть файл

@ -6,6 +6,7 @@
SOURCES += [
"CertDBTest.cpp",
"CertListTest.cpp",
"CoseTest.cpp",
"DataStorageTest.cpp",
"DeserializeCertTest.cpp",

Просмотреть файл

@ -896,8 +896,8 @@ nsNativeThemeGTK::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
const nsRect& aDirtyRect,
DrawOverflow aDrawOverflow) {
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return Theme::DrawWidgetBackground(
aContext, aFrame, aAppearance, aRect, aDirtyRect, aDrawOverflow);
return Theme::DrawWidgetBackground(aContext, aFrame, aAppearance, aRect,
aDirtyRect, aDrawOverflow);
}
GtkWidgetState state;
@ -1207,7 +1207,7 @@ bool nsNativeThemeGTK::GetWidgetOverflow(nsDeviceContext* aContext,
nsRect* aOverflowRect) {
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return Theme::GetWidgetOverflow(aContext, aFrame, aAppearance,
aOverflowRect);
aOverflowRect);
}
nsIntMargin extraSize;
@ -1232,8 +1232,7 @@ auto nsNativeThemeGTK::IsWidgetNonNative(nsIFrame* aFrame,
return NonNative::Always;
}
// We can't draw light widgets if the current GTK theme is dark or vice versa.
if (Theme::ThemeSupportsWidget(aFrame->PresContext(), aFrame,
aAppearance) &&
if (Theme::ThemeSupportsWidget(aFrame->PresContext(), aFrame, aAppearance) &&
LookAndFeel::ColorSchemeForFrame(aFrame) !=
LookAndFeel::ColorSchemeForChrome()) {
return NonNative::BecauseColorMismatch;
@ -1248,8 +1247,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
LayoutDeviceIntSize* aResult,
bool* aIsOverridable) {
if (IsWidgetNonNative(aFrame, aAppearance) == NonNative::Always) {
return Theme::GetMinimumWidgetSize(
aPresContext, aFrame, aAppearance, aResult, aIsOverridable);
return Theme::GetMinimumWidgetSize(aPresContext, aFrame, aAppearance,
aResult, aIsOverridable);
}
aResult->width = aResult->height = 0;
@ -1449,8 +1448,8 @@ nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame,
*aShouldRepaint = false;
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return Theme::WidgetStateChanged(
aFrame, aAppearance, aAttribute, aShouldRepaint, aOldValue);
return Theme::WidgetStateChanged(aFrame, aAppearance, aAttribute,
aShouldRepaint, aOldValue);
}
// Some widget types just never change state.
@ -1519,8 +1518,7 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
}
if (IsWidgetNonNative(aFrame, aAppearance) == NonNative::Always) {
return Theme::ThemeSupportsWidget(aPresContext, aFrame,
aAppearance);
return Theme::ThemeSupportsWidget(aPresContext, aFrame, aAppearance);
}
switch (aAppearance) {