#include "requirement.h"
#include "reqmaker.h"
#include "csutilities.h"
+#include <libDER/libDER.h>
+#include <libDER/asn1Types.h>
#include <security_utilities/cfutilities.h>
#include <security_utilities/hashing.h>
#include <security_cdsa_utilities/cssmdata.h> // OID coding
+#include <Security/SecCertificate.h>
using namespace CodeSigning;
typedef Requirement::Maker Maker;
+
+extern "C" {
+
+/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return
+an absoluteTime if the date was valid and properly decoded. Return
+NULL_TIME otherwise. */
+CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes,
+ size_t length);
+
+}
+
}
options {
void RequirementParser::certMatchOperation(Maker &maker, int32_t slot, string key)
{
- if (matchPrefix(key, "subject.")) {
+ if (const char *oids = matchPrefix(key, "timestamp.")) {
+ maker.put(opCertFieldDate);
+ maker.put(slot);
+ CssmAutoData oid(Allocator::standard()); oid.fromOid(oids);
+ maker.putData(oid.data(), oid.length());
+ } else if (matchPrefix(key, "subject.")) {
maker.put(opCertField);
maker.put(slot);
maker.put(key);
match_suffix[Maker &maker]
: empty ( "exists" ) ?
{ maker.put(matchExists); }
+ | "absent"
+ { maker.put(matchAbsent); }
| ( EQL | EQQL )
{ MatchOperation mop = matchEqual; string value; }
( STAR { mop = matchEndsWith; } ) ?
value=datavalue
( STAR { mop = (mop == matchEndsWith) ? matchContains : matchBeginsWith; } ) ?
{ maker.put(mop); maker.put(value); }
+ | ( EQL | EQQL )
+ { MatchOperation mop = matchOn; int64_t value; }
+ value=timestamp
+ { maker.put(mop); maker.put(value); }
| SUBS { string value; } value=datavalue
{ maker.put(matchContains); maker.put(value); }
| LESS { string value; } value=datavalue
{ maker.put(matchLessEqual); maker.put(value); }
| GE { string value; } value=datavalue
{ maker.put(matchGreaterEqual); maker.put(value); }
+ | LESS { int64_t value; } value=timestamp
+ { maker.put(matchBefore); maker.put(value); }
+ | GT { int64_t value; } value=timestamp
+ { maker.put(matchAfter); maker.put(value); }
+ | LE { int64_t value; } value=timestamp
+ { maker.put(matchOnOrBefore); maker.put(value); }
+ | GE { int64_t value; } value=timestamp
+ { maker.put(matchOnOrAfter); maker.put(value); }
;
bracketKey returns [string key]
: s:INTEGER { result = int32_t(atol(s->getText().c_str())); }
;
+// timestamps
+timestamp returns [int64_t result]
+ : "timestamp" s:STRING { result = (int64_t)SecAbsoluteTimeFromDateContent(ASN1_GENERALIZED_TIME, (uint8_t const *)s->getText().c_str(), s->getText().length()); }
+ ;
+
// syntactic cavity generators
fluff
: SEMI
k=2;
testLiterals=false;
- // Pass through valid UTF-8 (which excludes hex C0-C1 and F5-FF),
- // but also exclude ASCII control characters below 0x20 (space).
+ // Pass through valid UTF-8 (which excludes hex C0-C1 and F5-FF).
// Byte ranges according to Unicode 11.0, paragraph 3.9 D92.
charVocabulary='\000'..'\277' | '\302'..'\364';
}