Appearance
Simple Text Lexicon Version I
The goal of the SimpleTextV1Lexicon is to let policy definitions be written in a simple syntax, much like an if statement. The lexicon defines a small set of reserved tokens — binary and unary operators, plus literals that represent attributes and extensions of an X.509 certificate. Definitions can be as simple as a single comparison or as involved as a deeply nested, grouped, ternary expression.
Expressions are evaluated left to right, applying each operator in the order it appears. The policy engine has no operator precedence, but this lexicon lets you group and prioritize sub-expressions by wrapping them in parentheses.
Some operators evaluate to integers, but a policy definition as a whole must evaluate to a boolean. For example, the following is syntactically correct but fails in the engine because it evaluates only to an integer:
X509.TBS.EXTENSION.KeyUsage & 32This is meant to check whether the keyEncipherment bit of the key usage extension is set, using a bitwise AND — but the result of that expression is an integer, not a boolean. A valid statement wraps the bitwise AND and compares its result:
(X509.TBS.EXTENSION.KeyUsage & 32) > 0Note the parentheses. Strictly speaking they are not required, because operators are applied left to right with no precedence — but grouping expressions this way makes them clearer and avoids surprises. Consider what happens if the operands are reversed:
0 < X509.TBS.EXTENSION.KeyUsage & 32This fails. Evaluated left to right, 0 < X509.TBS.EXTENSION.KeyUsage produces a boolean, and the engine then tries to apply bitwise AND (&) to that boolean and the integer 32. Adding parentheses forces the bitwise AND to run first:
0 < (X509.TBS.EXTENSION.KeyUsage & 32)Formal Syntax Definition
The following is an EBNF definition of the Simple Text Version 1 lexicon:
letter = "A" | "B" | "C" | "D" | "E" | "F" | "G"
| "H" | "I" | "J" | "K" | "L" | "M" | "N"
| "O" | "P" | "Q" | "R" | "S" | "T" | "U"
| "V" | "W" | "X" | "Y" | "Z"
| "a" | "b" | "c" | "d" | "e" | "f" | "g"
| "h" | "i" | "j" | "k" | "l" | "m" | "n"
| "o" | "p" | "q" | "r" | "s" | "t" | "u"
| "v" | "w" | "x" | "y" | "z" ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
symbol = "[" | "]" | "." | "#" | "%" | "+" ;
unaryOperator = "^" | "{}" | "{}!" | "!" | "@@" ;
binaryOperator = "=" | "!=" | ">" | "<" | "$" | "{?}" | "{?}!" | "{}$"
| "{}&" | "||" | "&&" | "&" | "|" ;
operator = unaryOperator | binaryOperator ;
literalExpression = { letter | digit | symbol | white space} ;
rdnAttributeName = "CN" | "C" | "O" | "OU" | "ST" | "L" | "E" | "DC"
| "DNQUALIFIER" | "SERIALNUMBER" | "SN" | "TITLE" | "GIVENNAME"
| "INITIALS" | "PSEUDONYM" | "GERNERAL_QUALIFIER" | "DN" ;
x509Expression = "X509.Algorithm" | "X509.Signature" ;
tbsExpression = "X509.TBS.Version" | "X509.TBS.SerialNumber"
| "X509.TBS.Signature" | "X509.TBS.Issuer.", rdnAttributeName
| "X509.TBS.Validity.ValidFrom" | "X509.TBS.Validity.ValidTo"
| "X509.TBS.Subject.", rdnAttributeName | "X509.TBS.IssuerUniqueID"
| "X509.TBS.SubjectUniqueID" | "X509.TBS.SubjectPublicKeyInfo.Algorithm"
| "X509.TBS.SubjectPublicKeyInfo.Size" ;
extensionExpression = "X509.TBS.EXTENSION.KeyUsage" | "X509.TBS.EXTENSION.SubjectAltName"
| "X509.TBS.EXTENSION.SubjectDirectoryAttributes"
| "X509.TBS.EXTENSION.SubjectKeyIdentifier" | "X509.TBS.EXTENSION.IssuerAltName"
| "X509.TBS.EXTENSION.AuthorityKeyIdentifier.KeyId"
| "X509.TBS.EXTENSION.AuthorityKeyIdentifier.CertIssuers"
| "X509.TBS.EXTENSION.AuthorityKeyIdentifier.SerialNumber"
| "X509.TBS.EXTENSION.CertificatePolicies.PolicyOIDs"
| "X509.TBS.EXTENSION.CertificatePolicies.CPSUrls"
| "X509.TBS.EXTENSION.PolicyMappings" | "X509.TBS.EXTENSION.BasicConstraints.CA"
| "X509.TBS.EXTENSION.BasicConstraints.MaxPathLength"
| "X509.TBS.EXTENSION.NameConstraints" | "X509.TBS.EXTENSION.PolicyConstraints"
| "X509.TBS.EXTENSION.ExtKeyUsageSyntax" | "X509.TBS.EXTENSION.InhibitAnyPolicy"
| "X509.TBS.EXTENSION.CRLDistributionPoints.FullName"
| "X509.TBS.EXTENSION.CRLDistributionPoints.RelativeToIssuer"
| "X509.TBS.EXTENSION.CRLDistributionPoints.Reasons"
| "X509.TBS.EXTENSION.CRLDistributionPoints.CRLIssuer"
| "X509.TBS.EXTENSION.FreshestCRL.FullName"
| "X509.TBS.EXTENSION.FreshestCRL.RelativeToIssuer"
| "X509.TBS.EXTENSION.FreshestCRL.Reasons"
| "X509.TBS.EXTENSION.FreshestCRL.CRLIssuer"
| "X509.TBS.EXTENSION.AuthorityInfoAccessSyntax.Url"
| "X509.TBS.EXTENSION.AuthorityInfoAccessSyntax.OCSPLocation"
| "X509.TBS.EXTENSION.AuthorityInfoAccessSyntax.AccessMethod"
| "X509.TBS.EXTENSION.SubjectInfoAccessSyntax.Url"
| "X509.TBS.EXTENSION.SubjectInfoAccessSyntax.AccessMethod"
| "X509.TBS.EXTENSION.SubjectInfoAccessSyntax.OCSPLocation" ;
requiredExpression = tbsExpression, "+" | extensionExpression, "+" ;
certificateReferenceExpression = x509Expression | tbsExpression
| extensionExpression | requiredExpression ;
operatorExpression = [{(}] unaryOperator, [{white space}], (literalExpression | certificateReferenceExpression | operatorExpression) , [{)}] |
[{(}], (literalExpression | certificateReferenceExpression | operatorExpression) , [{white space}] , binaryOperator , [{white space}]
(literalExpression | certificateReferenceExpression | operatorExpression) , [{)}] ;
policyExpression = {operatorExpression}Literals
Literals are simply strings (white space included) and numbers used as operands. There is no special syntax to distinguish strings from numbers — the engine converts between them as needed. The elements of a collection literal are separated by commas (,). Boolean literals are written as the strings true and false.
Operators
The lexicon provides a small, focused set of operators for evaluating X.509 certificate attribute and extension values. Operators are either unary or binary, but they can immediately follow one another to form ternary expressions. The full list is enumerated in the PolicyOperator class.
Unary Operators
A unary operator precedes its single operand; white space may appear between the operator and the operand.
SIZE: ^
Takes a collection as its single operand and returns an integer: the number of elements in the collection.
EMPTY: {}
Takes a collection as its single operand and returns a boolean indicating whether the collection is empty (contains zero elements).
NOT EMPTY: {}!
Takes a collection as its single operand and returns a boolean indicating whether the collection is not empty (contains one or more elements).
LOGICAL NOT: !
Takes a boolean as its single operand and returns the opposite value: true becomes false, and false becomes true.
URI VALIDATE: @@
Takes a string representing a fully qualified URI as its single operand. It returns a boolean indicating whether the URI is syntactically correct and whether the URI resource exists and is reachable from the calling application.
Binary Operators
A binary operator takes two operands, one on each side, and is evaluated left to right.
EQUALS: =
Either operand may be of any type. Returns a boolean indicating whether the two operands are equal. Equality semantics depend on the operand type: if an operand is not a string or a number, the engine uses that object's equals method to determine equality.
NOT EQUALS: !=
Either operand may be of any type. Returns a boolean indicating whether the two operands are not equal. As with EQUALS, equality semantics depend on the operand type, and non-string, non-number operands are compared with their equals method.
GREATER THAN: >
Both operands must be numbers. Returns a boolean indicating whether the first operand is greater than the second.
LESS THAN: <
Both operands must be numbers. Returns a boolean indicating whether the first operand is less than the second.
REGEX: $
Both operands must be strings (numbers are treated as strings). Returns a boolean indicating whether the first operand, used as a regular expression, is found in the second operand. In other words, the first operand is the pattern to search for and the second operand is the string being searched.
CONTAINS: {?}
The first operand is an object of any type; the second is a collection of objects of any type. Returns a boolean indicating whether the first operand is present in the collection. Membership is tested with the Java collection's contains() method.
NOT CONTAINS: {?}!
The first operand is an object of any type; the second is a collection of objects of any type. Returns a boolean indicating whether the first operand is not present in the collection. As with CONTAINS, membership is tested with the Java collection's contains() method.
CONTAINS REGEX: {}$
The first operand is a string; the second is a collection of objects of any type. Returns a boolean indicating whether the first operand, used as a regular expression, matches any element of the collection. Non-string elements are converted to strings with their toString() method before matching.
INTERSECTION: {}&
Both operands are either a comma-delimited set of strings or a collection of objects of any type. Returns the set intersection of the two collections, computed with the Java collection's retainAll method. If the intersection is empty, an empty collection is returned. Comma-delimited strings are automatically converted to a collection of strings.
LOGICAL OR: ||
Both operands must be booleans (each may itself be the result of another boolean expression). Returns a boolean indicating whether at least one operand is true.
LOGICAL AND: &&
Both operands must be booleans (each may itself be the result of another boolean expression). Returns a boolean indicating whether both operands are true.
BITWISE OR: |
Both operands must be numbers. Returns a number produced by a bitwise OR of the two values.
BITWISE AND: &
Both operands must be numbers. Returns a number produced by a bitwise AND of the two values.
Certificate Reference Expressions
Certificate reference expressions are tokens that extract an attribute or extension value from an X.509 certificate. They fall into three categories, matching the structural sections of a certificate as defined by RFC 5280:
- Certificate attributes
- To-be-signed (TBS) attributes
- v3 extensions
The lexicon names many attributes and extensions (though not exhaustively), but the engine does not yet support all of them. The attributes most likely to be useful for policy checking are supported now; later versions of the engine will add more.
The following sections describe the level of support for each attribute and extension.
Certificate Attributes
These are the top-level attributes of every X.509 certificate.
X509.Algorithm
Extracts the algorithm used to sign the certificate. Returns the signature algorithm OID as a string. Commonly used OIDs are enumerated in the SignatureAlgorithmIdentifier class.
X509.Signature
Not yet supported.
To Be Signed Attributes
These attributes make up the to-be-signed (TBSCertificate) structure of every X.509 certificate. An attribute can be marked as required by appending the + token to the attribute token.
X509.TBS.Version
Not yet supported. Most current X.509 certificates use a value of 2, indicating version 3.
X509.TBS.SerialNumber
Extracts the certificate's serial number. Returns the serial number as a string in hexadecimal form, with no white space between digits. Hexadecimal digits represented by letters are lowercase, and leading zeros are removed.
X509.TBS.Signature
Not yet supported. This is always the same value as X509.Algorithm, as defined by section 4.1.2.3 of RFC 5280.
X509.TBS.Issuer.
Extracts a specific relative distinguished name (RDN) attribute from the certificate's Issuer field. Returns the value of the requested attribute as a string, or an empty string if the attribute is not found. Append the RDN attribute name to this token. Commonly used RDN names are enumerated in the RDNAttributeIdentifier class.
For example, the following token extracts the common name attribute from the Issuer field:
X509.TBS.Issuer.CNIf the CN had the value Test CN, then only Test CN would be returned — not CN=Test CN. The exception is the DN (distinguished name) attribute, which returns the entire distinguished name in RFC 2253 format. For example:
X509.TBS.Issuer.DNmight return something like:
O=Cerner,L=Kansas City,ST=MO,C=US,CN=test.email.comX509.TBS.Subject.
Identical to X509.TBS.Issuer., except that attributes are extracted from the Subject field rather than the Issuer field.
X509.TBS.Validity.ValidTo
Not yet supported.
X509.TBS.Validity.ValidFrom
Not yet supported.
X509.TBS.IssuerUniqueID
Not yet supported.
X509.TBS.SubjectPublicKeyInfo.Algorithm
Extracts the algorithm of the subject's public key. Returns the public key algorithm OID as a string. Commonly used OIDs are enumerated in the SignatureAlgorithmIdentifier class.
X509.TBS.SubjectPublicKeyInfo.Size
Extracts the size of the subject's public key. Returns the key size in bits as a number.
V3 Extensions
These are the v3 certificate extensions that make up the Extensions sequence of the X.509 certificate TBS structure. Any extension value can be marked as required by appending the + token to the extension token.
X509.TBS.EXTENSION.KeyUsage
Extracts the certificate's key usage extension. Returns a number that is the bitwise OR of the certificate's allowed key usages, or 0 if the extension is not present. All key usage bits are enumerated in the KeyUsageBit class.
X509.TBS.EXTENSION.SubjectAltName
Extracts the certificate's subject alternative name extension. Returns a collection of strings, where each string is the name type and the name itself joined by a colon (:). Returns an empty collection if the extension is not present. All name types are enumerated in the GeneralNameType class.
Example entry for a domain- or organization-bound certificate:
dns:direct.securehealthemail.comExample entry for an address-bound certificate:
rfc822:gm2552@direct.securehealthemail.comX509.TBS.EXTENSION.IssuerAltName
Identical to X509.TBS.EXTENSION.SubjectAltName, except that values are extracted from the issuer alternative name extension rather than the subject alternative name extension.
X509.TBS.EXTENSION.SubjectDirectoryAttributes
Not yet supported.
X509.TBS.EXTENSION.SubjectKeyIdentifier
Extracts the certificate's subject key identifier extension. Returns the key identifier as a string, or an empty string if the extension is not present.
X509.TBS.EXTENSION.AuthorityKeyIdentifier.KeyId
Extracts the keyId field of the certificate's authority key identifier extension. Returns the key identifier as a string, or an empty string if the extension is not present or the field is not populated.
X509.TBS.EXTENSION.AuthorityKeyIdentifier.CertIssuers
Not yet supported.
X509.TBS.EXTENSION.AuthorityKeyIdentifier.SerialNumber
Not yet supported.
X509.TBS.EXTENSION.CertificatePolicies.PolicyOIDs
Extracts the certificate's certificate policies extension. Returns a collection of strings containing the policy OIDs in the extension, or an empty collection if the extension is not present.
X509.TBS.EXTENSION.CertificatePolicies.CPSUrls
Extracts the CPS (Certification Practice Statement) URL field of the certificate's certificate policies extension. Returns a collection of strings containing the CPS URL for each policy OID that publishes one. Returns an empty collection if the extension is not present or if no policy OID populates the CPS URL field.
X509.TBS.EXTENSION.PolicyMappings
Not yet supported.
X509.TBS.EXTENSION.BasicConstraints.CA
Extracts the CA indicator field of the certificate's basic constraints extension. Returns a boolean: true if the certificate is a CA certificate, false if it is an end-entity certificate. Returns false if the extension is not present or the field is not populated.
X509.TBS.EXTENSION.BasicConstraints.MaxPathLength
Not yet supported.
X509.TBS.EXTENSION.NameConstraints
Not yet supported.
X509.TBS.EXTENSION.PolicyConstraints
Not yet supported.
X509.TBS.EXTENSION.ExtKeyUsageSyntax
Extracts the certificate's extended key usage extension. Returns a collection of strings containing the OIDs of the supported extended usages, or an empty collection if the extension is not present. Commonly used extended key usage OIDs are enumerated in the ExtendedKeyUsageIdentifier class.
X509.TBS.EXTENSION.InhibitAnyPolicy
Not yet supported.
X509.TBS.EXTENSION.CRLDistributionPoints.FullName
Extracts the full name field of the certificate's CRL distribution points extension. Returns a collection of strings containing the locations of the CRLs supported by the certificate, or an empty collection if the extension is not present or the FullName field is not populated.
These are generally URIs — for example, HTTP or HTTPS URLs — of the CRL distribution points.
X509.TBS.EXTENSION.CRLDistributionPoints.RelativeToIssuer
Not yet supported.
X509.TBS.EXTENSION.CRLDistributionPoints.Reasons
Not yet supported.
X509.TBS.EXTENSION.CRLDistributionPoints.CRLIssuer
Not yet supported.
X509.TBS.EXTENSION.FreshestCRL.FullName
Not yet supported.
X509.TBS.EXTENSION.FreshestCRL.RelativeToIssuer
Not yet supported.
X509.TBS.EXTENSION.FreshestCRL.Reasons
Not yet supported.
X509.TBS.EXTENSION.FreshestCRL.CRLIssuer
Not yet supported.
X509.TBS.EXTENSION.AuthorityInfoAccessSyntax.Url
Extracts the certificate's authority information access extension. Returns a collection of strings, where each string is the access method type and the access URL joined by a colon (:). Returns an empty collection if the extension is not present. All access method types are enumerated in the AuthorityInfoAccessMethodIdentifier class.
Example entry for a CA issuers URL:
caIssuers:http://ca.cerner.com/public/root.derExample entry for an OCSP URL:
OCSP:http://ca.cerner.com/OCSPX509.TBS.EXTENSION.SubjectInfoAccessSyntax.AccessMethod
Not yet supported. Use X509.TBS.EXTENSION.AuthorityInfoAccessSyntax.Url instead.
X509.TBS.EXTENSION.SubjectInfoAccessSyntax.OCSPLocation
Extracts the certificate's subject information access extension. Returns a collection of strings containing the URLs of entries that use the OCSP access method type. Returns an empty collection if the extension is not present or if no entries use the OCSP access method type.
