mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1029341: Factor out decoding of certificate/OCSP extensions, r=keeler
--HG-- extra : rebase_source : a1d66b75838e9dfad486f5654db6d977e5c1d97a extra : histedit_source : 34e05d8b3d94500b9cb4f1e311f8fe526b97ba6e
This commit is contained in:
parent
adfff88e33
commit
bf76dd549d
@ -661,6 +661,74 @@ OptionalVersion(Input& input, /*out*/ Version& version)
|
|||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ExtensionHandler>
|
||||||
|
inline Result
|
||||||
|
OptionalExtensions(Input& input, uint8_t tag, ExtensionHandler extensionHandler)
|
||||||
|
{
|
||||||
|
if (!input.Peek(tag)) {
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Input extensions;
|
||||||
|
{
|
||||||
|
Input tagged;
|
||||||
|
if (ExpectTagAndGetValue(input, tag, tagged) != Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
if (ExpectTagAndGetValue(tagged, SEQUENCE, extensions) != Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
if (End(tagged) != Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
||||||
|
//
|
||||||
|
// TODO(bug 997994): According to the specification, there should never be
|
||||||
|
// an empty sequence of extensions but we've found OCSP responses that have
|
||||||
|
// that (see bug 991898).
|
||||||
|
while (!extensions.AtEnd()) {
|
||||||
|
Input extension;
|
||||||
|
if (ExpectTagAndGetValue(extensions, SEQUENCE, extension)
|
||||||
|
!= Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension ::= SEQUENCE {
|
||||||
|
// extnID OBJECT IDENTIFIER,
|
||||||
|
// critical BOOLEAN DEFAULT FALSE,
|
||||||
|
// extnValue OCTET STRING
|
||||||
|
// }
|
||||||
|
Input extnID;
|
||||||
|
if (ExpectTagAndGetValue(extension, OIDTag, extnID) != Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
bool critical;
|
||||||
|
if (OptionalBoolean(extension, false, critical) != Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
SECItem extnValue;
|
||||||
|
if (ExpectTagAndGetValue(extension, OCTET_STRING, extnValue)
|
||||||
|
!= Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
if (End(extension) != Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool understood = false;
|
||||||
|
if (extensionHandler(extnID, extnValue, understood) != Success) {
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
if (critical && !understood) {
|
||||||
|
return Fail(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
// Parses a SEQUENCE into tbs and then parses an AlgorithmIdentifier followed
|
// Parses a SEQUENCE into tbs and then parses an AlgorithmIdentifier followed
|
||||||
// by a BIT STRING into signedData. This handles the commonality between
|
// by a BIT STRING into signedData. This handles the commonality between
|
||||||
// parsing the signed/signature fields of certificates and OCSP responses. In
|
// parsing the signed/signature fields of certificates and OCSP responses. In
|
||||||
|
@ -179,7 +179,9 @@ static inline der::Result ResponseData(
|
|||||||
/*const*/ SECItem* certs, size_t numCerts);
|
/*const*/ SECItem* certs, size_t numCerts);
|
||||||
static inline der::Result SingleResponse(der::Input& input,
|
static inline der::Result SingleResponse(der::Input& input,
|
||||||
Context& context);
|
Context& context);
|
||||||
static inline der::Result CheckExtensionsForCriticality(der::Input&);
|
static der::Result ExtensionNotUnderstood(der::Input& extnID,
|
||||||
|
const SECItem& extnValue,
|
||||||
|
/*out*/ bool& understood);
|
||||||
static inline der::Result CertID(der::Input& input,
|
static inline der::Result CertID(der::Input& input,
|
||||||
const Context& context,
|
const Context& context,
|
||||||
/*out*/ bool& match);
|
/*out*/ bool& match);
|
||||||
@ -531,14 +533,9 @@ ResponseData(der::Input& input, Context& context,
|
|||||||
return der::Failure;
|
return der::Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input.AtEnd()) {
|
return der::OptionalExtensions(input,
|
||||||
if (der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
|
der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
|
||||||
CheckExtensionsForCriticality) != der::Success) {
|
ExtensionNotUnderstood);
|
||||||
return der::Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return der::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SingleResponse ::= SEQUENCE {
|
// SingleResponse ::= SEQUENCE {
|
||||||
@ -656,11 +653,11 @@ SingleResponse(der::Input& input, Context& context)
|
|||||||
context.expired = true;
|
context.expired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input.AtEnd()) {
|
if (der::OptionalExtensions(input,
|
||||||
if (der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
|
der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
|
||||||
CheckExtensionsForCriticality) != der::Success) {
|
ExtensionNotUnderstood)
|
||||||
return der::Failure;
|
!= der::Success) {
|
||||||
}
|
return der::Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.thisUpdate) {
|
if (context.thisUpdate) {
|
||||||
@ -836,41 +833,14 @@ KeyHash(const SECItem& subjectPublicKeyInfo, /*out*/ uint8_t* hashBuf,
|
|||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extension ::= SEQUENCE {
|
der::Result
|
||||||
// extnID OBJECT IDENTIFIER,
|
ExtensionNotUnderstood(der::Input& /*extnID*/, const SECItem& /*extnValue*/,
|
||||||
// critical BOOLEAN DEFAULT FALSE,
|
/*out*/ bool& understood)
|
||||||
// extnValue OCTET STRING
|
|
||||||
// }
|
|
||||||
static der::Result
|
|
||||||
CheckExtensionForCriticality(der::Input& input)
|
|
||||||
{
|
{
|
||||||
// TODO: maybe we should check the syntax of the OID value
|
understood = false;
|
||||||
if (ExpectTagAndSkipValue(input, der::OIDTag) != der::Success) {
|
|
||||||
return der::Failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The only valid explicit encoding of the value is TRUE, so don't even
|
|
||||||
// bother parsing it, since we're going to fail either way.
|
|
||||||
if (input.Peek(der::BOOLEAN)) {
|
|
||||||
return der::Fail(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
input.SkipToEnd();
|
|
||||||
|
|
||||||
return der::Success;
|
return der::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
|
||||||
static der::Result
|
|
||||||
CheckExtensionsForCriticality(der::Input& input)
|
|
||||||
{
|
|
||||||
// TODO(bug 997994): some responders include an empty SEQUENCE OF
|
|
||||||
// Extension, which is invalid (der::MayBeEmpty should really be
|
|
||||||
// der::MustNotBeEmpty).
|
|
||||||
return der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
|
|
||||||
der::EmptyAllowed::Yes, CheckExtensionForCriticality);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. The certificate identified in a received response corresponds to
|
// 1. The certificate identified in a received response corresponds to
|
||||||
// the certificate that was identified in the corresponding request;
|
// the certificate that was identified in the corresponding request;
|
||||||
// 2. The signature on the response is valid;
|
// 2. The signature on the response is valid;
|
||||||
|
Loading…
Reference in New Issue
Block a user