The TCG EK cert profile says that the context tags in the
TPMSecurityAssertions type are IMPLICIT. The sample EK cert we have
has them as EXPLICIT.
What to do?
Status:
- And it works!
- We have an extensive test based on decoding a rich EK certficate.
This test exercises all of:
- decoding
- encoding with and without decoded open types
- copying of decoded values with decoded open types
- freeing of decoded values with decoded open types
Valgrind finds no memory errors.
- Added a manual page for the compiler.
- rfc2459.asn1 now has all three primary PKIX types that we care about
defined as in RFC5912, with IOS constraints and parameterization:
- `Extension` (embeds open type in an `OCTET STRING`)
- `OtherName` (embeds open type in an `ANY`-like type)
- `SingleAttribute` (embeds open type in an `ANY`-like type)
- `AttributeSet` (embeds open type in a `SET OF ANY`-like type)
All of these use OIDs as the open type type ID field, but integer
open type type ID fields are also supported (and needed, for
Kerberos).
That will cover every typed hole pattern in all our ASN.1 modules.
With this we'll be able to automatically and recursively decode
through all subject DN attributes even when the subject DN is a
directoryName SAN, and subjectDirectoryAttributes, and all
extensions, and all SANs, and all authorization-data elements, and
PA-data, and...
We're not really using `SingleAttribute` and `AttributeSet` yet
because various changes are needed in `lib/hx509` for that.
- `asn1_compile` builds and recognizes the subset of X.681/682/683 that
we need for, and now use in, rfc2459.asn1. It builds the necessary
AST, generates the correct C types, and generates templating for
object sets and open types!
- See READMEs for details.
- Codegen backend not tested; I won't make it implement automatic open
type handling, but it should at least not crash by substituting
`heim_any` for open types not embedded in `OCTET STRING`.
- We're _really_ starting to have problems with the ITU-T ASN.1
grammar and our version of it...
Type names have to start with upper-case, value names with
lower-case, but it's not enough to disambiguate.
The fact the we've allowed value and type names to violate their
respective start-with case rules is causing us trouble now that we're
adding grammar from X.681/682/683, and we're going to have to undo
that.
In preparation for that I'm capitalizing the `heim_any` and
`heim_any_set` types, and doing some additional cleanup, which
requires changes to other parts of Heimdal (all in this same commit
for now).
Problems we have because of this:
- We cannot IMPORT values into modules because we have no idea if a
symbol being imported refers to a value or a type because the only
clue we would have is the symbol's name, so we assume IMPORTed
symbols are for types.
This means we can't import OIDs, for example, which is super
annoying.
One thing we might be able to do here is mark imported symbols as
being of an undetermined-but-not-undefined type, then coerce the
symbol's type the first time it's used in a context where its type
is inferred as type, value, object, object set, or class. (Though
since we don't generate C symbols for objects or classes, we won't
be able to import them, especially since we need to know them at
compile time and cannot defer their handling to link- or
run-time.)
- The `NULL` type name, and the `NULL` value name now cause two
reduce/reduce conflicts via the `FieldSetting` production.
- Various shift/reduce conflicts involving `NULL` values in
non-top-level contexts (in constraints, for example).
- Currently I have a bug where to disambiguate the grammar I have a
CLASS_IDENTIFIER token that is all caps, while TYPE_IDENTIFIER must
start with a capital but not be all caps, but this breaks Kerberos
since all its types are all capitalized -- oof!
To fix this I made it so class names have to be all caps and
start with an underscore (ick).
TBD:
- Check all the XXX comments and address them
- Apply this treatment to Kerberos! Automatic handling of authz-data
sounds useful :)
- Apply this treatment to PKCS#10 (CSRs) and other ASN.1 modules too.
- Replace various bits of code in `lib/hx509/` with uses of this
feature.
- Add JER.
- Enhance `hxtool` and `asn1_print`.
Getting there!
Now that the ASN.1 compiler properly supports IMPLICIT tagging of named
CHOICE types (meaning: treat them as EXPLICIT tags), we can remove one
workaround for that.
The template compiler was applying IMPLICIT tags to CHOICE types. This
is very wrong, as the tag of a CHOICE's taken choice cannot be replaced
without making it impossible to figure out what the choice was. An
example of this is GeneralName's directoryName, which is an IMPLICIT-
tagged CHOICE.
Separately, the non-template compiler was requiring inlining of
IMPLICIT-tagged CHOICEs, which also happens in GeneralName's
directoryName case:
```
205 Name ::= CHOICE {
206 rdnSequence RDNSequence
207 }
...
287 GeneralName ::= CHOICE {
288 otherName [0] IMPLICIT -- OtherName --
SEQUENCE {
289 type-id OBJECT IDENTIFIER,
290 value [0] EXPLICIT heim_any
291 },
292 rfc822Name [1] IMPLICIT IA5String,
293 dNSName [2] IMPLICIT IA5String,
294 -- x400Address [3] IMPLICIT ORAddress,--
--->295 directoryName [4] IMPLICIT -- Name -- CHOICE
{
296 rdnSequence RDNSequence
297 },
298 -- ediPartyName [5] IMPLICIT EDIPartyName, --
299 uniformResourceIdentifier [6] IMPLICIT IA5String,
300 iPAddress [7] IMPLICIT OCTET STRING,
301 registeredID [8] IMPLICIT OBJECT IDENTIFIER
302 }
```
Anyways, that's fixed now, though changing that will require making
corresponding changes to `lib/hx509/`.
We're getting closer to parity between the two compilers. The template
compiler is still missing support for `SET { ... }` types. Speaking of
`SET { ... }`, the regular compiler generates code that uses `qsort()`
to sort the encoded values values of the members of such a set, but this
seems silly because the order of members is knowable at compile time, as
for DER and CER the order by the tags of the members, from lowest to
highest (see X.690, section 9.3 and X.680, section 8.6). As it happens
using `qsort()` on the encodings of the members works, but it would be
be better to sort in `lib/asn1/asn1parse.y` and then not have to bother
anywhere else. Sorting SETs at definition time will help keep the
tamplate compiler simple. Not that we _need_ `SET { ... }` for anything
in-tree other than the X.690 sample...
While we're at it, let's note that the core of PKIX from the RFC
2459/3280/5280/5912 consists of *two* ASN.1 modules, one with
default-EXPLICIT tags, and one with default-IMPLICIT tags, and
Heimdal has these merged as a default-EXPLICIT tags module in
`lib/asn1/rfc2459.asn1`, with `IMPLICIT` added in by hand in all the
tags in the default-IMPLICIT tagged module. This fixes one recently
added type from PKIX that didn't have `IMPLICIT` added in manually!
This is necessary in order to add proper support for CSRs in kx509,
where the KDC can examine all requested KUs/EKUs/SANs, check
authorization, and issue a certificate with all those extensions if
authorized.
This is the convention used by OpenSSL, of encoding all the KU, EKUs,
and SANs being requested as Extensions as they would appear in the
TBSCertificate, then putting those in as a single Attribute in the CSR's
Attributes list with attribute OID {id-pkcs-9, 14}.
- expose all hx509_request_*() functions
- finish support in hx509_request_parse*() for KU, EKU, and SAN CSR
attributes
- finish support in hx509_request_to_pkcs10() for encoding all
requested KU, EKU, and SAN extensions as a CSR extReq (extension request)
- add hx509_request_add_*() support for:
- id-pkinit-san and ms-upn-pkinit-san
- XMPP (Jabber) SAN
- registeredID (useless but trivial)
- add hxtool request-create options for all supported SANs
- add hxtool request-create options for KeyUsage
- add hxtool request-create options for ExtKeyUsage
- add hxtool request-print support for all these things
- fix bugs in existing id-pkinit-san handling
Possible future improvements
- add HX509_TRACE env var and support (it would be nice to be able to
observe why some certificate is rejected, or not matched in a query)
- add testing that CSR creating and printing round-trip for all KUs,
EKUs, and SANs
(probably in tests/kdc/check-pkinit.in)
- add testing that OpenSSL can print a CSR made by hxtool and
vice-versa
- hxtool ca: add KU sanity checking (via hx509_ca_sign() and/or friends)
(don't allow encrypt for signing-only algs)
(don't allow encrypt for RSA at all, or for RSA with small e exponents)
- hxtool request-print: warn about all unknown attributes and
extensions
- hxtool ca: MAYBE add support for adding requested extensions from the
--req=CSR
("Maybe" because CA operators should really verify and authorize all
requested attributes, and should acknowledge that they have, and the
simplest way to do this is to make them add all the corresponding
CLI arguments to the hxtool ca command, but too, that is
error-prone, thus it's not clear yet which approach is best.
Perhaps interactively prompt for yes/no for each attribute.)
- add additional SAN types:
- iPAddress (useless?)
- dNSSrv (useful!)
- directoryName (useless, but trivial)
- uniformResourceIdentifier (useful)
- it would be nice if the ASN.1 compiler could generate print
functions..., and/or even better, to-JSON functions
- it would be nice if we had a known-OID db, including the names of the
types they refer to in certificate extensions, otherName SANs and CSR
attributes, then we could generate a CSR and certificate printer for
all known options even when they are not supported by the rest of
Heimdal
- and we could also get friendly names for OIDs, and we could
resolve their arc names
- longer term, we could also stand to add some ASN.1 information
object system functionality, just enough to make
lib/hx509/asn1_print awesome by being able to automatically decode
all heim_any and OCTET STRING content (better than its current
--inner option)