asn1: Enrich asn1_print with schema

Our asn1_print, like OpenSSL's, just knows how to parse and dump DER.
Ours can attempt to decode OCTET STRING and IMPLICIT-tagged constructed
values as DER, which is very useful.

But _now_ it's even better.  Now it knows about all types exported from
all ASN.1 modules in `lib/asn1/` in Heimdal, and if told to print as
some type, it will use the new printing interface to print JSON-like
representations of values:

```
$ ./asn1_print /tmp/t490/ek2.crt Certificate |
  jq '.tbsCertificate.extensions[3]._extnValue[]._values'
[
  {
    "_type": "TPMSpecification",
    "family": "2.0",
    "level": "0",
    "revision": "138"
  }
]
[
  {
    "_type": "TPMSecurityAssertions",
    "version": "0",
    "fieldUpgradable": true,
    "ekGenerationType": "655617",
    "ekGenerationLocation": "655616",
    "ekCertificateGenerationLocation": "655616",
    "ccInfo": {
      "_type": "CommonCriteriaMeasures",
      "version": "3.1",
      "assurancelevel": "4",
      "evaluationStatus": "2",
      "plus": true,
      "strengthOfFunction": null,
      "profileOid": null,
      "profileUri": null,
      "targetOid": null,
      "targetUri": null
    },
    "fipsLevel": {
      "_type": "FIPSLevel",
      "version": "140-2",
      "level": "2",
      "plus": false
    },
    "iso9000Certified": false,
    "iso9000Uri": null
  }
]
```
This commit is contained in:
Nicolas Williams
2021-02-24 21:08:17 -06:00
parent fb2c81f3e8
commit ece3c688e0
4 changed files with 911 additions and 35 deletions

View File

@@ -9,10 +9,10 @@ annotations](/lib/asn1/README-X681.md).
1. [Introduction](#Introduction)
2. [ASN.1 Support in Heimdal](#asn1-support-in-heimdal)
3. [News](#News)
4. [Features](#Features)
5. [Limitations](#Limitations)
6. [Compiler Usage](#Compiler-usage)
3. [Features](#Features)
4. [Limitations](#Limitations)
5. [Compiler Usage](#Compiler-usage)
6. [asn1_print Usage](#asn1_print-usage)
7. [Implementation](#implementation)
8. [Moving From C](#moving-from-c)
@@ -164,7 +164,7 @@ make it easy to add support for encoding rules other than X.690.
```bash
$ ./asn1_print ek.crt Certificate |
jq '.tbsCertificate.extensions[3]._open_type[]._open_type'
jq '.tbsCertificate.extensions[3]._extnValue[]._values'
```
```JSON
@@ -180,7 +180,7 @@ make it easy to add support for encoding rules other than X.690.
{
"_type": "TPMSecurityAssertions",
"version": "0",
"fieldUpgradable": "1",
"fieldUpgradable": true,
"ekGenerationType": "655617",
"ekGenerationLocation": "655616",
"ekCertificateGenerationLocation": "655616",
@@ -189,7 +189,7 @@ make it easy to add support for encoding rules other than X.690.
"version": "3.1",
"assurancelevel": "4",
"evaluationStatus": "2",
"plus": "1",
"plus": true,
"strengthOfFunction": null,
"profileOid": null,
"profileUri": null,
@@ -200,14 +200,564 @@ make it easy to add support for encoding rules other than X.690.
"_type": "FIPSLevel",
"version": "140-2",
"level": "2",
"plus": "0"
"plus": false
},
"iso9000Certified": "0",
"iso9000Certified": false,
"iso9000Uri": null
}
]
```
A complete dump of such a certificate:
```bash
$ ./asn1_print ek.crt Certificate | jq .
```
```JSON
{
"_type": "Certificate",
"tbsCertificate": {
"_type": "TBSCertificate",
"_save": "30820376A00302010202146A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A300D06092A864886F70D01010B05003055310B3009060355040613024348311E301C060355040A131553544D6963726F656C656374726F6E696373204E56312630240603550403131D53544D2054504D20454B20496E7465726D656469617465204341203035301E170D3138313231343030303030305A170D3238313231343030303030305A300030820122300D06092A864886F70D01010105000382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001A38201A9308201A5301F0603551D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C0866030420603551D20043B303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F30590603551D110101FF044F304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A303034393030303830670603551D090460305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100300E0603551D0F0101FF040403020520300C0603551D130101FF0402300030100603551D250409300706056781050801304A06082B06010505070101043E303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
"version": "2",
"serialNumber": "6A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A",
"signature": {
"_type": "AlgorithmIdentifier",
"algorithm": {
"_type": "OBJECT IDENTIFIER",
"oid": "1.2.840.113549.1.1.11",
"components": [
1,
2,
840,
113549,
1,
1,
11
],
"name": "id-pkcs1-sha256WithRSAEncryption"
},
"parameters": "0500"
},
"issuer": {
"_choice": "rdnSequence",
"value": [
[
{
"_type": "AttributeTypeAndValue",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.4.6",
"components": [
2,
5,
4,
6
],
"name": "id-at-countryName"
},
"value": {
"_choice": "printableString",
"value": "CH"
}
}
],
[
{
"_type": "AttributeTypeAndValue",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.4.10",
"components": [
2,
5,
4,
10
],
"name": "id-at-organizationName"
},
"value": {
"_choice": "printableString",
"value": "STMicroelectronics NV"
}
}
],
[
{
"_type": "AttributeTypeAndValue",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.4.3",
"components": [
2,
5,
4,
3
],
"name": "id-at-commonName"
},
"value": {
"_choice": "printableString",
"value": "STM TPM EK Intermediate CA 05"
}
}
]
]
},
"validity": {
"_type": "Validity",
"notBefore": {
"_choice": "utcTime",
"value": "2018-12-14T00:00:00Z"
},
"notAfter": {
"_choice": "utcTime",
"value": "2028-12-14T00:00:00Z"
}
},
"subject": {
"_choice": "rdnSequence",
"value": []
},
"subjectPublicKeyInfo": {
"_type": "SubjectPublicKeyInfo",
"algorithm": {
"_type": "AlgorithmIdentifier",
"algorithm": {
"_type": "OBJECT IDENTIFIER",
"oid": "1.2.840.113549.1.1.1",
"components": [
1,
2,
840,
113549,
1,
1,
1
],
"name": "id-pkcs1-rsaEncryption"
},
"parameters": "0500"
},
"subjectPublicKey": "2160:3082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001"
},
"issuerUniqueID": null,
"subjectUniqueID": null,
"extensions": [
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.35",
"components": [
2,
5,
29,
35
],
"name": "id-x509-ce-authorityKeyIdentifier"
},
"critical": false,
"extnValue": "301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660",
"_extnValue_choice": "ext-AuthorityKeyIdentifier",
"_extnValue": {
"_type": "AuthorityKeyIdentifier",
"keyIdentifier": "1ADB994AB58BE57A0CC9B900E7851E1A43C08660",
"authorityCertIssuer": null,
"authorityCertSerialNumber": null
}
},
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.32",
"components": [
2,
5,
29,
32
],
"name": "id-x509-ce-certificatePolicies"
},
"critical": false,
"extnValue": "303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F",
"_extnValue_choice": "ext-CertificatePolicies",
"_extnValue": [
{
"_type": "PolicyInformation",
"policyIdentifier": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.32.0",
"components": [
2,
5,
29,
32,
0
],
"name": "id-x509-ce-certificatePolicies-anyPolicy"
},
"policyQualifiers": [
{
"_type": "PolicyQualifierInfo",
"policyQualifierId": {
"_type": "OBJECT IDENTIFIER",
"oid": "1.3.6.1.5.5.7.2.1",
"components": [
1,
3,
6,
1,
5,
5,
7,
2,
1
],
"name": "id-pkix-qt-cps"
},
"qualifier": "1621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F"
}
]
}
]
},
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.17",
"components": [
2,
5,
29,
17
],
"name": "id-x509-ce-subjectAltName"
},
"critical": true,
"extnValue": "304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A3030343930303038",
"_extnValue_choice": "ext-SubjectAltName",
"_extnValue": [
{
"_choice": "directoryName",
"value": {
"_choice": "rdnSequence",
"value": [
[
{
"_type": "AttributeTypeAndValue",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.23.133.2.1",
"components": [
2,
23,
133,
2,
1
],
"name": "tcg-at-tpmManufacturer"
},
"value": {
"_choice": "utf8String",
"value": "id:53544D20"
}
}
],
[
{
"_type": "AttributeTypeAndValue",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.23.133.2.2",
"components": [
2,
23,
133,
2,
2
],
"name": "tcg-at-tpmModel"
},
"value": {
"_choice": "utf8String",
"value": "ST33HTPHAHC0"
}
}
],
[
{
"_type": "AttributeTypeAndValue",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.23.133.2.3",
"components": [
2,
23,
133,
2,
3
],
"name": "tcg-at-tpmVersion"
},
"value": {
"_choice": "utf8String",
"value": "id:00490008"
}
}
]
]
}
}
]
},
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.9",
"components": [
2,
5,
29,
9
],
"name": "id-x509-ce-subjectDirectoryAttributes"
},
"critical": false,
"extnValue": "305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100",
"_extnValue_choice": "ext-SubjectDirectoryAttributes",
"_extnValue": [
{
"_type": "AttributeSet",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.23.133.2.16",
"components": [
2,
23,
133,
2,
16
],
"name": "tcg-at-tpmSpecification"
},
"values": [
"300C0C03322E300201000202008A"
],
"_values_choice": "at-TPMSpecification",
"_values": [
{
"_type": "TPMSpecification",
"family": "2.0",
"level": 0,
"revision": 138
}
]
},
{
"_type": "AttributeSet",
"type": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.23.133.2.18",
"components": [
2,
23,
133,
2,
18
],
"name": "tcg-at-tpmSecurityAssertions"
},
"values": [
"30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100"
],
"_values_choice": "at-TPMSecurityAssertions",
"_values": [
{
"_type": "TPMSecurityAssertions",
"version": "0",
"fieldUpgradable": true,
"ekGenerationType": "655617",
"ekGenerationLocation": "655616",
"ekCertificateGenerationLocation": "655616",
"ccInfo": {
"_type": "CommonCriteriaMeasures",
"version": "3.1",
"assurancelevel": "4",
"evaluationStatus": "2",
"plus": true,
"strengthOfFunction": null,
"profileOid": null,
"profileUri": null,
"targetOid": null,
"targetUri": null
},
"fipsLevel": {
"_type": "FIPSLevel",
"version": "140-2",
"level": "2",
"plus": false
},
"iso9000Certified": false,
"iso9000Uri": null
}
]
}
]
},
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.15",
"components": [
2,
5,
29,
15
],
"name": "id-x509-ce-keyUsage"
},
"critical": true,
"extnValue": "03020520",
"_extnValue_choice": "ext-KeyUsage",
"_extnValue": [
"keyEncipherment"
]
},
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.19",
"components": [
2,
5,
29,
19
],
"name": "id-x509-ce-basicConstraints"
},
"critical": true,
"extnValue": "3000",
"_extnValue_choice": "ext-BasicConstraints",
"_extnValue": {
"_type": "BasicConstraints",
"cA": false,
"pathLenConstraint": null
}
},
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "2.5.29.37",
"components": [
2,
5,
29,
37
],
"name": "id-x509-ce-extKeyUsage"
},
"critical": false,
"extnValue": "300706056781050801",
"_extnValue_choice": "ext-ExtKeyUsage",
"_extnValue": [
{
"_type": "OBJECT IDENTIFIER",
"oid": "2.23.133.8.1",
"components": [
2,
23,
133,
8,
1
],
"name": "tcg-kp-EKCertificate"
}
]
},
{
"_type": "Extension",
"extnID": {
"_type": "OBJECT IDENTIFIER",
"oid": "1.3.6.1.5.5.7.1.1",
"components": [
1,
3,
6,
1,
5,
5,
7,
1,
1
],
"name": "id-pkix-pe-authorityInfoAccess"
},
"critical": false,
"extnValue": "303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
"_extnValue_choice": "ext-AuthorityInfoAccess",
"_extnValue": [
{
"_type": "AccessDescription",
"accessMethod": {
"_type": "OBJECT IDENTIFIER",
"oid": "1.3.6.1.5.5.7.48.2",
"components": [
1,
3,
6,
1,
5,
5,
7,
48,
2
],
"name": "id-pkix-ad-caIssuers"
},
"accessLocation": {
"_choice": "uniformResourceIdentifier",
"value": "http://secure.globalsign.com/stmtpmekint05.crt"
}
}
]
}
]
},
"signatureAlgorithm": {
"_type": "AlgorithmIdentifier",
"algorithm": {
"_type": "OBJECT IDENTIFIER",
"oid": "1.2.840.113549.1.1.11",
"components": [
1,
2,
840,
113549,
1,
1,
11
],
"name": "id-pkcs1-sha256WithRSAEncryption"
},
"parameters": "0500"
},
"signatureValue": "2048:3D4C381E5B4F1BCBE09C63D52F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF8869013041E92CDD3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAFF9E7E908480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252A4C18A4F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20EB3DBD763F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63BE0E516D00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B38F7EE56CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755BBC2806FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506"
}
```
(Notice that OID names look a bit weird. For reasons that may have been
lost to time and may no longer be relevant, these OIDs are defined with
slightly different names in the ASN.1 modules in Heimdal's source tree.
We'll fix this eventually.)
- Unconstrained integer types have a large integer representation in C that is
not terribly useful in common cases. Range constraints on integer types
cause the compiler to use `int32_t`, `int64_t`, `uint32_t`, and/or
@@ -349,6 +899,46 @@ HEIMDAL February 22, 2021 HEIMDAL
```
## asn1_print Usage
```
ASN1_PRINT(1) BSD General Commands Manual ASN1_PRINT(1)
NAME
asn1_print — dump ASN.1 DER encoded values
SYNOPSIS
asn1_print [-i | --no-indent] [-I | --inner] [-l | --list-types]
[-l -v | --version] [-l -h | --help] [FILE [TypeName]]
DESCRIPTION
asn1_print Dumps ASN.1 DER-encoded values. If a TypeName is given, then
asn1_print will print the value in a JSON-like format using its knowledge
of the ASN.1 module defining that type. If a TypeName is given, it must
be the name of an ASN.1 type exported by an ASN.1 module that is compiled
into asn1_print. Use the --list-types option to list ASN.1 types known
to asn1_print.
Options supported:
-i, --no-indent
Do not indent dump.
-I, --inner
Try to parse inner structures of OCTET STRING and constructed
values.
-l, --list-types
Try to parse inner structures of OCTET STRING and constructed
values.
-v, --version
-h, --help
HEIMDAL February 22, 2021 HEIMDAL
```
## Implementation
...

94
lib/asn1/asn1_print.1 Normal file
View File

@@ -0,0 +1,94 @@
.\" Copyright (c) 2021 Kungliga Tekniska Högskolan
.\" (Royal Institute of Technology, Stockholm, Sweden).
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id$
.\"
.Dd February 22, 2021
.Dt ASN1_PRINT 1
.Os HEIMDAL
.Sh NAME
.Nm asn1_print
.Nd dump ASN.1 DER encoded values
.Sh SYNOPSIS
.Nm
.Bk -words
.Oo Fl i \*(Ba Xo
.Fl Fl no-indent
.Xc
.Oc
.Oo Fl I \*(Ba Xo
.Fl Fl inner
.Xc
.Oc
.Oo Fl l \*(Ba Xo
.Fl Fl list-types
.Xc
.Oc
.Oo Fl l v \*(Ba Xo
.Fl Fl version
.Xc
.Oc
.Oo Fl l h \*(Ba Xo
.Fl Fl help
.Xc
.Oc
.Op Ar FILE Op Ar TypeName
.Ek
.Sh DESCRIPTION
.Nm
Dumps ASN.1 DER-encoded values.
If a
.Ar TypeName
is given, then
.Nm
will print the value in a JSON-like format using its knowledge of
the ASN.1 module defining that type.
If a
.Ar TypeName
is given, it must be the name of an ASN.1 type exported by an
ASN.1 module that is compiled into
.Nm .
Use the
.Fl Fl list-types
option to list ASN.1 types known to
.Nm .
.Pp
Options supported:
.Bl -tag -width Ds
.It Fl i, Fl Fl no-indent
Do not indent dump.
.It Fl I, Fl Fl inner
Try to parse inner structures of OCTET STRING and constructed values.
.It Fl l, Fl Fl list-types
Try to parse inner structures of OCTET STRING and constructed values.
.It Fl v, Fl Fl version
.It Fl h, Fl Fl help
.El

View File

@@ -37,9 +37,23 @@
#include <com_err.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <getarg.h>
#include <err.h>
#include <der.h>
#include "cms_asn1.h"
#include "digest_asn1.h"
#include "krb5_asn1.h"
#include "kx509_asn1.h"
#include "ocsp_asn1.h"
#include "pkcs10_asn1.h"
#include "pkcs12_asn1.h"
#include "pkcs8_asn1.h"
#include "pkcs9_asn1.h"
#include "pkinit_asn1.h"
#include "rfc2459_asn1.h"
#include "rfc4108_asn1.h"
#include "x690sample_asn1.h"
static int indent_flag = 1;
static int inner_flag = 0;
@@ -47,6 +61,41 @@ static int inner_flag = 0;
static unsigned long indefinite_form_loop;
static unsigned long indefinite_form_loop_max = 10000;
typedef int (*decoder)(const unsigned char *, size_t, void *, size_t *);
typedef char *(*printer)(const void *, int);
typedef void (*releaser)(void *);
struct types {
const char *name;
decoder decode;
printer print;
releaser release;
size_t sz;
} types[] = {
#define ASN1_SYM_INTVAL(n, gn, gns, i)
#define ASN1_SYM_OID(n, gn, gns)
#define ASN1_SYM_TYPE(n, gn, gns) \
{ \
n, \
(decoder)decode_ ## gns, \
(printer)print_ ## gns, \
(releaser)free_ ## gns, \
sizeof(gns) \
},
#include "cms_asn1_syms.x"
#include "digest_asn1_syms.x"
#include "krb5_asn1_syms.x"
#include "kx509_asn1_syms.x"
#include "ocsp_asn1_syms.x"
#include "pkcs10_asn1_syms.x"
#include "pkcs12_asn1_syms.x"
#include "pkcs8_asn1_syms.x"
#include "pkcs9_asn1_syms.x"
#include "pkinit_asn1_syms.x"
#include "rfc2459_asn1_syms.x"
#include "rfc4108_asn1_syms.x"
#include "x690sample_asn1_syms.x"
};
static size_t
loop (unsigned char *buf, size_t len, int indent)
{
@@ -289,44 +338,161 @@ loop (unsigned char *buf, size_t len, int indent)
}
static int
doit (const char *filename)
type_cmp(const void *va, const void *vb)
{
int fd = open (filename, O_RDONLY);
const struct types *ta = (const struct types *)va;
const struct types *tb = (const struct types *)vb;
return strcmp(ta->name, tb->name);
}
static int
doit(const char *filename, const char *typename)
{
int fd = open(filename, O_RDONLY);
struct stat sb;
unsigned char *buf;
size_t len;
int ret;
if(fd < 0)
err (1, "opening %s for read", filename);
err(1, "opening %s for read", filename);
if (fstat (fd, &sb) < 0)
err (1, "stat %s", filename);
err(1, "stat %s", filename);
len = sb.st_size;
buf = emalloc (len);
if (read (fd, buf, len) != len)
errx (1, "read failed");
close (fd);
ret = loop (buf, len, 0);
free (buf);
buf = emalloc(len);
if (read(fd, buf, len) != len)
errx(1, "read failed");
close(fd);
if (typename) {
struct types *sorted_types = emalloc(sizeof(types));
size_t right = sizeof(types)/sizeof(types[0]) - 1;
size_t left = 0;
size_t mid;
size_t sz;
char *s;
void *v;
int c = -1;
memcpy(sorted_types, types, sizeof(types));
qsort(sorted_types,
sizeof(types)/sizeof(types[0]),
sizeof(types[0]),
type_cmp);
while (left <= right) {
mid = (left + right) >> 1;
c = strcmp(sorted_types[mid].name, typename);
if (c < 0)
left = mid + 1;
else if (c > 0)
right = mid - 1;
else
break;
}
if (c != 0)
errx(1, "Type %s not found", typename);
v = ecalloc(1, sorted_types[mid].sz);
ret = sorted_types[mid].decode(buf, len, v, &sz);
if (ret == 0) {
s = sorted_types[mid].print(v,
indent_flag ? ASN1_PRINT_INDENT : 0);
sorted_types[mid].release(v);
if (!s)
ret = errno;
}
if (ret == 0) {
fprintf(stdout, "%s\n", s);
free(buf);
free(s);
exit(0);
}
switch (ret) {
case ASN1_BAD_TIMEFORMAT:
errx(1, "Could not decode and print data as type %s: "
"Bad time format", typename);
case ASN1_MISSING_FIELD:
errx(1, "Could not decode and print data as type %s: "
"Missing required field", typename);
case ASN1_MISPLACED_FIELD:
errx(1, "Could not decode and print data as type %s: "
"Fields out of order", typename);
case ASN1_TYPE_MISMATCH:
errx(1, "Could not decode and print data as type %s: "
"Type mismatch", typename);
case ASN1_OVERFLOW:
errx(1, "Could not decode and print data as type %s: "
"DER value too large", typename);
case ASN1_OVERRUN:
errx(1, "Could not decode and print data as type %s: "
"DER value too short", typename);
case ASN1_BAD_ID:
errx(1, "Could not decode and print data as type %s: "
"DER tag is unexpected", typename);
case ASN1_BAD_LENGTH:
errx(1, "Could not decode and print data as type %s: "
"DER length does not match value", typename);
case ASN1_BAD_FORMAT:
case ASN1_PARSE_ERROR:
errx(1, "Could not decode and print data as type %s: "
"DER badly formatted", typename);
case ASN1_EXTRA_DATA:
errx(1, "Could not decode and print data as type %s: "
"Extra data past end of end structure", typename);
case ASN1_BAD_CHARACTER:
errx(1, "Could not decode and print data as type %s: "
"Invalid character encoding in string", typename);
case ASN1_MIN_CONSTRAINT:
errx(1, "Could not decode and print data as type %s: "
"Too few elements", typename);
case ASN1_MAX_CONSTRAINT:
errx(1, "Could not decode and print data as type %s: "
"Too many elements", typename);
case ASN1_EXACT_CONSTRAINT:
errx(1, "Could not decode and print data as type %s: "
"Wrong count of elements", typename);
case ASN1_INDEF_OVERRUN:
errx(1, "Could not decode and print data as type %s: "
"BER indefinte encoding overun", typename);
case ASN1_INDEF_UNDERRUN:
errx(1, "Could not decode and print data as type %s: "
"BER indefinte encoding underun", typename);
case ASN1_GOT_BER:
errx(1, "Could not decode and print data as type %s: "
"BER encoding when DER expected", typename);
case ASN1_INDEF_EXTRA_DATA:
errx(1, "Could not decode and print data as type %s: "
"End-of-contents tag contains data", typename);
default:
err(1, "Could not decode and print data as type %s", typename);
}
}
ret = loop(buf, len, 0);
free(buf);
return ret;
}
static int list_types_flag = 0;
static int version_flag;
static int help_flag;
struct getargs args[] = {
{ "indent", 0, arg_negative_flag, &indent_flag, NULL, NULL },
{ "inner", 0, arg_flag, &inner_flag,
"try to parse inner structures of OCTET STRING", NULL },
{ "version", 0, arg_flag, &version_flag, NULL, NULL },
{ "help", 0, arg_flag, &help_flag, NULL, NULL }
{ "indent", 'i', arg_negative_flag, &indent_flag,
"\tdo not indent dump", NULL },
{ "inner", 'I', arg_flag, &inner_flag,
"\ttry to parse inner structures of OCTET STRING", NULL },
{ "list-types", 'l', arg_flag, &list_types_flag,
"\tlist ASN.1 types known to this program", NULL },
{ "version", 'v', arg_flag, &version_flag, NULL, NULL },
{ "help", 'h', arg_flag, &help_flag, NULL, NULL }
};
int num_args = sizeof(args) / sizeof(args[0]);
static void
usage(int code)
{
arg_printusage(args, num_args, NULL, "dump-file");
arg_printusage(args, num_args, NULL, "dump-file [TypeName]");
exit(code);
}
@@ -335,19 +501,29 @@ main(int argc, char **argv)
{
int optidx = 0;
setprogname (argv[0]);
initialize_asn1_error_table ();
if(getarg(args, num_args, argc, argv, &optidx))
setprogname(argv[0]);
initialize_asn1_error_table();
if (getarg(args, num_args, argc, argv, &optidx))
usage(1);
if(help_flag)
if (help_flag)
usage(0);
if(version_flag) {
if (version_flag) {
print_version(NULL);
exit(0);
}
argv += optidx;
argc -= optidx;
if (argc != 1)
usage (1);
return doit (argv[0]);
if (list_types_flag) {
size_t i;
if (argc)
usage(1);
for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)
printf("%s\n", types[i].name);
exit(0);
}
if (argc != 1 && argc != 2)
usage(1);
return doit(argv[0], argv[1]);
}

View File

@@ -41,6 +41,7 @@ extern int prefix_enum;
RCSID("$Id$");
FILE *privheaderfile, *headerfile, *oidsfile, *codefile, *logfile, *templatefile;
FILE *symsfile;
#define STEM "asn1"
@@ -285,6 +286,11 @@ init_generate (const char *filename, const char *base)
oidsfile = fopen(fn, "w");
if (oidsfile == NULL)
err (1, "open %s", fn);
if (asprintf(&fn, "%s_syms.x", base) < 0 || fn == NULL)
errx(1, "malloc");
symsfile = fopen(fn, "w");
if (symsfile == NULL)
err (1, "open %s", fn);
free(fn);
fn = NULL;
@@ -462,6 +468,10 @@ generate_constant (const Symbol *s)
"enum { %s = %lld };\n\n",
s->gen_name, s->gen_name, s->gen_name,
(long long)s->value->u.integervalue);
if (is_export(s->name))
fprintf(symsfile, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
s->name, s->gen_name, s->gen_name,
(long long)s->value->u.integervalue);
break;
case nullvalue:
break;
@@ -508,6 +518,9 @@ generate_constant (const Symbol *s)
s->gen_name, (unsigned long)len, s->gen_name);
fprintf(oidsfile, "DEFINE_OID_WITH_NAME(%s)\n", s->gen_name);
if (is_export(s->name))
fprintf(symsfile, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
s->name, s->gen_name, s->gen_name);
free(list);
@@ -1606,6 +1619,9 @@ generate_type_header (const Symbol *s)
if (s->emitted_definition)
return;
if (is_export(s->name))
fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
s->name, s->gen_name, s->gen_name);
fprintf(headerfile, "typedef ");
define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE,
preserve_type(s->name) ? TRUE : FALSE);
@@ -1632,7 +1648,7 @@ generate_type (const Symbol *s)
if (!one_code_file)
generate_header_of_codefile(s->gen_name);
generate_type_header (s);
generate_type_header(s);
if (template_flag)
generate_template(s);
@@ -1691,5 +1707,5 @@ generate_type (const Symbol *s)
if (!one_code_file) {
fprintf(codefile, "\n\n");
close_codefile();
}
}
}