Result BackCert::Init() { Result rv; // Certificate ::= SEQUENCE { // tbsCertificate TBSCertificate, // signatureAlgorithm AlgorithmIdentifier, // signatureValue BIT STRING } Reader tbsCertificate; // The scope of |input| and |certificate| are limited to this block so we // don't accidentally confuse them for tbsCertificate later. { Reader certificate; rv = der::ExpectTagAndGetValueAtEnd(der, der::SEQUENCE, certificate); if (rv != Success) { return rv; } rv = der::SignedData(certificate, tbsCertificate, signedData); if (rv != Success) { return rv; } rv = der::End(certificate); if (rv != Success) { return rv; } } // TBSCertificate ::= SEQUENCE { // version [0] EXPLICIT Version DEFAULT v1, // serialNumber CertificateSerialNumber, // signature AlgorithmIdentifier, // issuer Name, // validity Validity, // subject Name, // subjectPublicKeyInfo SubjectPublicKeyInfo, // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, // -- If present, version MUST be v2 or v3 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, // -- If present, version MUST be v2 or v3 // extensions [3] EXPLICIT Extensions OPTIONAL // -- If present, version MUST be v3 // } rv = der::OptionalVersion(tbsCertificate, version); if (rv != Success) { return rv; } rv = der::CertificateSerialNumber(tbsCertificate, serialNumber); if (rv != Success) { return rv; } rv = der::ExpectTagAndGetValue(tbsCertificate, der::SEQUENCE, signature); if (rv != Success) { return rv; } rv = der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE, issuer); if (rv != Success) { return rv; } rv = der::ExpectTagAndGetValue(tbsCertificate, der::SEQUENCE, validity); if (rv != Success) { return rv; } // TODO(bug XXXXXXX): We rely on the the caller of mozilla::pkix to validate // that the name is syntactically valid, if they care. In Gecko we do this // implicitly by parsing the certificate into a CERTCertificate object. // Instead of relying on the caller to do this, we should do it ourselves. rv = der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE, subject); if (rv != Success) { return rv; } rv = der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE, subjectPublicKeyInfo); if (rv != Success) { return rv; } static const uint8_t CSC = der::CONTEXT_SPECIFIC | der::CONSTRUCTED; // According to RFC 5280, all fields below this line are forbidden for // certificate versions less than v3. However, for compatibility reasons, // we parse v1/v2 certificates in the same way as v3 certificates. So if // these fields appear in a v1 certificate, they will be used. // Ignore issuerUniqueID if present. if (tbsCertificate.Peek(CSC | 1)) { rv = der::ExpectTagAndSkipValue(tbsCertificate, CSC | 1); if (rv != Success) { return rv; } } // Ignore subjectUniqueID if present. if (tbsCertificate.Peek(CSC | 2)) { rv = der::ExpectTagAndSkipValue(tbsCertificate, CSC | 2); if (rv != Success) { return rv; } } rv = der::OptionalExtensions( tbsCertificate, CSC | 3, [this](Reader& extnID, const Input& extnValue, bool critical, /*out*/ bool& understood) { return RememberExtension(extnID, extnValue, critical, understood); }); if (rv != Success) { return rv; } // The Netscape Certificate Type extension is an obsolete // Netscape-proprietary mechanism that we ignore in favor of the standard // extensions. However, some CAs have issued certificates with the Netscape // Cert Type extension marked critical. Thus, for compatibility reasons, we // "understand" this extension by ignoring it when it is not critical, and // by ensuring that the equivalent standardized extensions are present when // it is marked critical, based on the assumption that the information in // the Netscape Cert Type extension is consistent with the information in // the standard extensions. // // Here is a mapping between the Netscape Cert Type extension and the // standard extensions: // // Netscape Cert Type | BasicConstraints.cA | Extended Key Usage // --------------------+-----------------------+---------------------- // SSL Server | false | id_kp_serverAuth // SSL Client | false | id_kp_clientAuth // S/MIME Client | false | id_kp_emailProtection // Object Signing | false | id_kp_codeSigning // SSL Server CA | true | id_pk_serverAuth // SSL Client CA | true | id_kp_clientAuth // S/MIME CA | true | id_kp_emailProtection // Object Signing CA | true | id_kp_codeSigning if (criticalNetscapeCertificateType.GetLength() > 0 && (basicConstraints.GetLength() == 0 || extKeyUsage.GetLength() == 0)) { return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION; } return der::End(tbsCertificate); }
void CombinedEventDelta::RememberExtensions(const SmartPointer<ExtensionPoint>& extensionPoint, const QList<int>& exts) { for (int i = 0; i < exts.size(); ++i) RememberExtension(extensionPoint, exts[i]); }