bug 985021 - mozilla::pkix: temporarily accept pathLenConstraint in EE basic constraints extensions r=briansmith

This commit is contained in:
David Keeler 2014-03-21 10:38:36 -07:00
parent f819eba2cb
commit 81f6c14f73
2 changed files with 76 additions and 4 deletions

View File

@ -147,6 +147,62 @@ CheckCertificatePolicies(BackCert& cert, EndEntityOrCA endEntityOrCA,
return RecoverableError; return RecoverableError;
} }
// BasicConstraints ::= SEQUENCE {
// cA BOOLEAN DEFAULT FALSE,
// pathLenConstraint INTEGER (0..MAX) OPTIONAL }
der::Result
DecodeBasicConstraints(const SECItem* encodedBasicConstraints,
CERTBasicConstraints& basicConstraints)
{
PR_ASSERT(encodedBasicConstraints);
if (!encodedBasicConstraints) {
return der::Fail(SEC_ERROR_INVALID_ARGS);
}
basicConstraints.isCA = false;
basicConstraints.pathLenConstraint = 0;
der::Input input;
if (input.Init(encodedBasicConstraints->data, encodedBasicConstraints->len)
!= der::Success) {
return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
}
if (der::ExpectTagAndIgnoreLength(input, der::SEQUENCE) != der::Success) {
return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
}
bool isCA = false;
if (der::OptionalBoolean(input, isCA) != der::Success) {
return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
}
basicConstraints.isCA = isCA;
if (input.Peek(der::INTEGER)) {
SECItem pathLenConstraintEncoded;
if (der::Integer(input, pathLenConstraintEncoded) != der::Success) {
return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
}
long pathLenConstraint = DER_GetInteger(&pathLenConstraintEncoded);
if (pathLenConstraint >= std::numeric_limits<int>::max() ||
pathLenConstraint < 0) {
return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
}
basicConstraints.pathLenConstraint = static_cast<int>(pathLenConstraint);
// TODO(bug 985025): If isCA is false, pathLenConstraint MUST NOT
// be included (as per RFC 5280 section 4.2.1.9), but for compatibility
// reasons, we don't check this for now.
} else if (basicConstraints.isCA) {
// If this is a CA but the path length is omitted, it is unlimited.
basicConstraints.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
}
if (der::End(input) != der::Success) {
return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
}
return der::Success;
}
// RFC5280 4.2.1.9. Basic Constraints (id-ce-basicConstraints) // RFC5280 4.2.1.9. Basic Constraints (id-ce-basicConstraints)
Result Result
CheckBasicConstraints(const BackCert& cert, CheckBasicConstraints(const BackCert& cert,
@ -156,10 +212,9 @@ CheckBasicConstraints(const BackCert& cert,
{ {
CERTBasicConstraints basicConstraints; CERTBasicConstraints basicConstraints;
if (cert.encodedBasicConstraints) { if (cert.encodedBasicConstraints) {
SECStatus rv = CERT_DecodeBasicConstraintValue(&basicConstraints, if (DecodeBasicConstraints(cert.encodedBasicConstraints,
cert.encodedBasicConstraints); basicConstraints) != der::Success) {
if (rv != SECSuccess) { return RecoverableError;
return MapSECStatus(rv);
} }
} else { } else {
// Synthesize a non-CA basic constraints by default // Synthesize a non-CA basic constraints by default

View File

@ -380,6 +380,23 @@ Boolean(Input& input, /*out*/ bool& value)
} }
} }
// This is for any BOOLEAN DEFAULT FALSE.
// (If it is present and false, this is a bad encoding.)
inline Result
OptionalBoolean(Input& input, /*out*/ bool& value)
{
value = false;
if (input.Peek(BOOLEAN)) {
if (Boolean(input, value) != Success) {
return Failure;
}
if (!value) {
return Fail(SEC_ERROR_BAD_DER);
}
}
return Success;
}
inline Result inline Result
Enumerated(Input& input, uint8_t& value) Enumerated(Input& input, uint8_t& value)
{ {