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:
Brian Smith 2014-07-10 22:38:59 -07:00
parent cb04dd761f
commit 76608dbfec
7 changed files with 90 additions and 85 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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

View File

@ -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()),

View File

@ -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

View File

@ -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;
}