mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1037324: Delegate additional name constraint selection to the TrustDomain in mozilla::pkix, r=cviecco
--HG-- extra : rebase_source : 300f33bfb3a0c9ae1525695b080674c1fb21eafc
This commit is contained in:
parent
cb04dd761f
commit
76608dbfec
@ -113,7 +113,9 @@ AppTrustDomain::FindIssuer(const SECItem& encodedIssuerName,
|
||||
for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
|
||||
!CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
|
||||
bool keepGoing;
|
||||
SECStatus srv = checker.Check(n->cert->derCert, keepGoing);
|
||||
SECStatus srv = checker.Check(n->cert->derCert,
|
||||
nullptr/*additionalNameConstraints*/,
|
||||
keepGoing);
|
||||
if (srv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -61,6 +61,51 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
|
||||
{
|
||||
}
|
||||
|
||||
// E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
|
||||
static const uint8_t ANSSI_SUBJECT_DATA[] =
|
||||
"\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04"
|
||||
"\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03"
|
||||
"\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65"
|
||||
"\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05"
|
||||
"\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03"
|
||||
"\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44"
|
||||
"\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13"
|
||||
"\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06"
|
||||
"\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41"
|
||||
"\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7"
|
||||
"\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40"
|
||||
"\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75"
|
||||
"\x76\x2E\x66\x72";
|
||||
|
||||
static const SECItem ANSSI_SUBJECT = {
|
||||
siBuffer,
|
||||
const_cast<uint8_t*>(ANSSI_SUBJECT_DATA),
|
||||
sizeof(ANSSI_SUBJECT_DATA) - 1
|
||||
};
|
||||
|
||||
static const uint8_t PERMIT_FRANCE_GOV_NAME_CONSTRAINTS_DATA[] =
|
||||
"\x30\x5D" // SEQUENCE (length=93)
|
||||
"\xA0\x5B" // permittedSubtrees (length=91)
|
||||
"\x30\x05\x82\x03" ".fr"
|
||||
"\x30\x05\x82\x03" ".gp"
|
||||
"\x30\x05\x82\x03" ".gf"
|
||||
"\x30\x05\x82\x03" ".mq"
|
||||
"\x30\x05\x82\x03" ".re"
|
||||
"\x30\x05\x82\x03" ".yt"
|
||||
"\x30\x05\x82\x03" ".pm"
|
||||
"\x30\x05\x82\x03" ".bl"
|
||||
"\x30\x05\x82\x03" ".mf"
|
||||
"\x30\x05\x82\x03" ".wf"
|
||||
"\x30\x05\x82\x03" ".pf"
|
||||
"\x30\x05\x82\x03" ".nc"
|
||||
"\x30\x05\x82\x03" ".tf";
|
||||
|
||||
static const SECItem PERMIT_FRANCE_GOV_NAME_CONSTRAINTS = {
|
||||
siBuffer,
|
||||
const_cast<uint8_t*>(PERMIT_FRANCE_GOV_NAME_CONSTRAINTS_DATA),
|
||||
sizeof(PERMIT_FRANCE_GOV_NAME_CONSTRAINTS_DATA) - 1
|
||||
};
|
||||
|
||||
SECStatus
|
||||
NSSCertDBTrustDomain::FindIssuer(const SECItem& encodedIssuerName,
|
||||
IssuerChecker& checker, PRTime time)
|
||||
@ -73,8 +118,14 @@ NSSCertDBTrustDomain::FindIssuer(const SECItem& encodedIssuerName,
|
||||
if (candidates) {
|
||||
for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
|
||||
!CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
|
||||
const SECItem* additionalNameConstraints = nullptr;
|
||||
// TODO: Use CERT_CompareName or equivalent
|
||||
if (SECITEM_ItemsAreEqual(&encodedIssuerName, &ANSSI_SUBJECT)) {
|
||||
additionalNameConstraints = &PERMIT_FRANCE_GOV_NAME_CONSTRAINTS;
|
||||
}
|
||||
bool keepGoing;
|
||||
SECStatus srv = checker.Check(n->cert->derCert, keepGoing);
|
||||
SECStatus srv = checker.Check(n->cert->derCert,
|
||||
additionalNameConstraints, keepGoing);
|
||||
if (srv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -146,8 +146,16 @@ public:
|
||||
class IssuerChecker
|
||||
{
|
||||
public:
|
||||
// potentialIssuerDER is the complete DER encoding of the certificate to
|
||||
// be checked as a potential issuer.
|
||||
//
|
||||
// If additionalNameConstraints is not nullptr then it must point to an
|
||||
// encoded NameConstraints extension value; in that case, those name
|
||||
// constraints will be checked in addition to any any name constraints
|
||||
// contained in potentialIssuerDER.
|
||||
virtual SECStatus Check(const SECItem& potentialIssuerDER,
|
||||
/*out*/ bool& keepGoing) = 0;
|
||||
/*optional*/ const SECItem* additionalNameConstraints,
|
||||
/*out*/ bool& keepGoing) = 0;
|
||||
protected:
|
||||
IssuerChecker();
|
||||
virtual ~IssuerChecker();
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
}
|
||||
|
||||
SECStatus Check(const SECItem& potentialIssuerDER,
|
||||
/*optional*/ const SECItem* additionalNameConstraints,
|
||||
/*out*/ bool& keepGoing);
|
||||
|
||||
Result CheckResult() const;
|
||||
@ -130,6 +131,7 @@ PathBuildingStep::CheckResult() const
|
||||
// The code that executes in the inner loop of BuildForward
|
||||
SECStatus
|
||||
PathBuildingStep::Check(const SECItem& potentialIssuerDER,
|
||||
/*optional*/ const SECItem* additionalNameConstraints,
|
||||
/*out*/ bool& keepGoing)
|
||||
{
|
||||
BackCert potentialIssuer(potentialIssuerDER, EndEntityOrCA::MustBeCA,
|
||||
@ -157,9 +159,20 @@ PathBuildingStep::Check(const SECItem& potentialIssuerDER,
|
||||
}
|
||||
}
|
||||
|
||||
rv = CheckNameConstraints(potentialIssuer, requiredEKUIfPresent);
|
||||
if (rv != Success) {
|
||||
return RecordResult(PR_GetError(), keepGoing);
|
||||
if (potentialIssuer.GetNameConstraints()) {
|
||||
rv = CheckNameConstraints(*potentialIssuer.GetNameConstraints(),
|
||||
subject, requiredEKUIfPresent);
|
||||
if (rv != Success) {
|
||||
return RecordResult(PR_GetError(), keepGoing);
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalNameConstraints) {
|
||||
rv = CheckNameConstraints(*additionalNameConstraints, subject,
|
||||
requiredEKUIfPresent);
|
||||
if (rv != Success) {
|
||||
return RecordResult(PR_GetError(), keepGoing);
|
||||
}
|
||||
}
|
||||
|
||||
// RFC 5280, Section 4.2.1.3: "If the keyUsage extension is present, then the
|
||||
|
@ -412,81 +412,10 @@ PORT_FreeArena_false(PLArenaPool* arena) {
|
||||
}
|
||||
|
||||
Result
|
||||
CheckNameConstraints(const BackCert& cert, KeyPurposeId requiredEKUIfPresent)
|
||||
CheckNameConstraints(const SECItem& encodedNameConstraints,
|
||||
const BackCert& firstChild,
|
||||
KeyPurposeId requiredEKUIfPresent)
|
||||
{
|
||||
// These hardcoded consts are to handle a post certificate creation
|
||||
// name constraints. In this case for ANSSI.
|
||||
static const char constraintFranceGov[] =
|
||||
"\x30\x5D" /* sequence len 93*/
|
||||
"\xA0\x5B" /* element len 91 */
|
||||
"\x30\x05" /* sequence len 5 */
|
||||
"\x82\x03" /* entry len 3 */
|
||||
".fr"
|
||||
"\x30\x05\x82\x03" /* sequence len 5, entry len 3 */
|
||||
".gp"
|
||||
"\x30\x05\x82\x03"
|
||||
".gf"
|
||||
"\x30\x05\x82\x03"
|
||||
".mq"
|
||||
"\x30\x05\x82\x03"
|
||||
".re"
|
||||
"\x30\x05\x82\x03"
|
||||
".yt"
|
||||
"\x30\x05\x82\x03"
|
||||
".pm"
|
||||
"\x30\x05\x82\x03"
|
||||
".bl"
|
||||
"\x30\x05\x82\x03"
|
||||
".mf"
|
||||
"\x30\x05\x82\x03"
|
||||
".wf"
|
||||
"\x30\x05\x82\x03"
|
||||
".pf"
|
||||
"\x30\x05\x82\x03"
|
||||
".nc"
|
||||
"\x30\x05\x82\x03"
|
||||
".tf";
|
||||
|
||||
/* The stringified value for the subject is:
|
||||
E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
|
||||
*/
|
||||
static const char rawANSSISubject[] =
|
||||
"\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04"
|
||||
"\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03"
|
||||
"\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65"
|
||||
"\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05"
|
||||
"\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03"
|
||||
"\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44"
|
||||
"\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13"
|
||||
"\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06"
|
||||
"\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41"
|
||||
"\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7"
|
||||
"\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40"
|
||||
"\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75"
|
||||
"\x76\x2E\x66\x72";
|
||||
|
||||
const SECItem ANSSI_SUBJECT = {
|
||||
siBuffer,
|
||||
reinterpret_cast<uint8_t *>(const_cast<char *>(rawANSSISubject)),
|
||||
sizeof(rawANSSISubject) - 1
|
||||
};
|
||||
|
||||
const SECItem PERMIT_FRANCE_GOV_NC = {
|
||||
siBuffer,
|
||||
reinterpret_cast<uint8_t *>(const_cast<char *>(constraintFranceGov)),
|
||||
sizeof(constraintFranceGov) - 1
|
||||
};
|
||||
|
||||
const SECItem* nameConstraintsToUse = cert.GetNameConstraints();
|
||||
|
||||
if (!nameConstraintsToUse) {
|
||||
if (SECITEM_ItemsAreEqual(&cert.GetSubject(), &ANSSI_SUBJECT)) {
|
||||
nameConstraintsToUse = &PERMIT_FRANCE_GOV_NC;
|
||||
} else {
|
||||
return Success;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedPtr<PLArenaPool, PORT_FreeArena_false>
|
||||
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
|
||||
if (!arena) {
|
||||
@ -495,13 +424,12 @@ CheckNameConstraints(const BackCert& cert, KeyPurposeId requiredEKUIfPresent)
|
||||
|
||||
// Owned by arena
|
||||
const CERTNameConstraints* constraints =
|
||||
CERT_DecodeNameConstraintsExtension(arena.get(), nameConstraintsToUse);
|
||||
CERT_DecodeNameConstraintsExtension(arena.get(), &encodedNameConstraints);
|
||||
if (!constraints) {
|
||||
return MapSECStatus(SECFailure);
|
||||
}
|
||||
|
||||
for (const BackCert* child = cert.childCert; child;
|
||||
child = child->childCert) {
|
||||
for (const BackCert* child = &firstChild; child; child = child->childCert) {
|
||||
ScopedPtr<CERTCertificate, CERT_DestroyCertificate>
|
||||
nssCert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
|
||||
const_cast<SECItem*>(&child->GetDER()),
|
||||
|
@ -41,7 +41,8 @@ Result CheckIssuerIndependentProperties(
|
||||
unsigned int subCACount,
|
||||
/*optional out*/ TrustLevel* trustLevel = nullptr);
|
||||
|
||||
Result CheckNameConstraints(const BackCert& cert,
|
||||
Result CheckNameConstraints(const SECItem& encodedNameConstraints,
|
||||
const BackCert& firstChild,
|
||||
KeyPurposeId requiredEKUIfPresent);
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
@ -135,7 +135,9 @@ private:
|
||||
for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
|
||||
!CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
|
||||
bool keepGoing;
|
||||
SECStatus srv = checker.Check(n->cert->derCert, keepGoing);
|
||||
SECStatus srv = checker.Check(n->cert->derCert,
|
||||
nullptr/*additionalNameConstraints*/,
|
||||
keepGoing);
|
||||
if (srv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user