asn1: Add printing of ASN.1 values

JSON-like printing of ASN.1 parsed values.

Status:

 - Not X.697 (JER) compliant, not even close.

 - String escaping isn't JSON-compliant.

 - It's not printing the names of CHOICE types.

 - It's not printing the names of open type choices (i.e., IOS object
   names)

And yet it's quite useful already.  It prints all the weird things in EK
certs for example.

Here's what it outputs for the EK cert we use in check-gen.c:

{
  "_type": "Certificate",
  "tbsCertificate": {
    "_type": "TBSCertificate",
    "_save": "30820376A00302010202146A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A300D06092A864886F70D01010B05003055310B3009060355040613024348311E301C060355040A131553544D6963726F656C656374726F6E696373204E56312630240603550403131D53544D2054504D20454B20496E7465726D656469617465204341203035301E170D3138313231343030303030305A170D3238313231343030303030305A300030820122300D06092A864886F70D01010105000382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001A38201A9308201A5301F0603551D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C0866030420603551D20043B303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F30590603551D110101FF044F304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A303034393030303830670603551D090460305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100300E0603551D0F0101FF040403020520300C0603551D130101FF0402300030100603551D250409300706056781050801304A06082B06010505070101043E303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
    "version": "2",
    "serialNumber": "6A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A",
    "signature": {
      "_type": "AlgorithmIdentifier",
      "algorithm": "1.2.840.113549.1.1.11",
      "parameters": "0500"
    },
    "issuer": {
      "_choice": "rdnSequence",
      "value": [
        [
          {
            "_type": "AttributeTypeAndValue",
            "type": "2.5.4.6",
            "value": {
              "_choice": "printableString",
              "value": "CH"
            }
          }
        ],
        [
          {
            "_type": "AttributeTypeAndValue",
            "type": "2.5.4.10",
            "value": {
              "_choice": "printableString",
              "value": "STMicroelectronics NV"
            }
          }
        ],
        [
          {
            "_type": "AttributeTypeAndValue",
            "type": "2.5.4.3",
            "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": "1.2.840.113549.1.1.1",
        "parameters": "0500"
      },
      "subjectPublicKey": "2160:3082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001"
    },
    "issuerUniqueID": null,
    "subjectUniqueID": null,
    "extensions": [
      {
        "_type": "Extension",
        "extnID": "2.5.29.35",
        "critical": false,
        "extnValue": "301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660",
        "_extnValue": {
          "_type": "AuthorityKeyIdentifier",
          "keyIdentifier": "1ADB994AB58BE57A0CC9B900E7851E1A43C08660",
          "authorityCertIssuer": null,
          "authorityCertSerialNumber": null
        }
      },
      {
        "_type": "Extension",
        "extnID": "2.5.29.32",
        "critical": false,
        "extnValue": "303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F",
        "_extnValue": [
          {
            "_type": "PolicyInformation",
            "policyIdentifier": "2.5.29.32.0",
            "policyQualifiers": [
              {
                "_type": "PolicyQualifierInfo",
                "policyQualifierId": "1.3.6.1.5.5.7.2.1",
                "qualifier": "1621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F"
              }
            ]
          }
        ]
      },
      {
        "_type": "Extension",
        "extnID": "2.5.29.17",
        "critical": true,
        "extnValue": "304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A3030343930303038",
        "_extnValue": [
          {
            "_choice": "directoryName",
            "value": {
              "_choice": "rdnSequence",
              "value": [
                [
                  {
                    "_type": "AttributeTypeAndValue",
                    "type": "2.23.133.2.1",
                    "value": {
                      "_choice": "utf8String",
                      "value": "id:53544D20"
                    }
                  }
                ],
                [
                  {
                    "_type": "AttributeTypeAndValue",
                    "type": "2.23.133.2.2",
                    "value": {
                      "_choice": "utf8String",
                      "value": "ST33HTPHAHC0"
                    }
                  }
                ],
                [
                  {
                    "_type": "AttributeTypeAndValue",
                    "type": "2.23.133.2.3",
                    "value": {
                      "_choice": "utf8String",
                      "value": "id:00490008"
                    }
                  }
                ]
              ]
            }
          }
        ]
      },
      {
        "_type": "Extension",
        "extnID": "2.5.29.9",
        "critical": false,
        "extnValue": "305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100",
        "_extnValue": [
          {
            "_type": "AttributeSet",
            "type": "2.23.133.2.16",
            "values": [
              "300C0C03322E300201000202008A"
            ],
            "_values": [
              {
                "_type": "TPMSpecification",
                "family": "2.0",
                "level": "0",
                "revision": "138"
              }
            ]
          },
          {
            "_type": "AttributeSet",
            "type": "2.23.133.2.18",
            "values": [
              "30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100"
            ],
            "_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": "2.5.29.15",
        "critical": true,
        "extnValue": "03020520",
        "_extnValue": [
          "keyEncipherment"
        ]
      },
      {
        "_type": "Extension",
        "extnID": "2.5.29.19",
        "critical": true,
        "extnValue": "3000",
        "_extnValue": {
          "_type": "BasicConstraints",
          "cA": false,
          "pathLenConstraint": null
        }
      },
      {
        "_type": "Extension",
        "extnID": "2.5.29.37",
        "critical": false,
        "extnValue": "300706056781050801",
        "_extnValue": [
          "2.23.133.8.1"
        ]
      },
      {
        "_type": "Extension",
        "extnID": "1.3.6.1.5.5.7.1.1",
        "critical": false,
        "extnValue": "303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
        "_extnValue": [
          {
            "_type": "AccessDescription",
            "accessMethod": "1.3.6.1.5.5.7.48.2",
            "accessLocation": {
              "_choice": "uniformResourceIdentifier",
              "value": "http://secure.globalsign.com/stmtpmekint05.crt"
            }
          }
        ]
      }
    ]
  },
  "signatureAlgorithm": {
    "_type": "AlgorithmIdentifier",
    "algorithm": "1.2.840.113549.1.1.11",
    "parameters": "0500"
  },
  "signatureValue": "2048:3D4C381E5B4F1BCBE09C63D52F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF8869013041E92CDD3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAFF9E7E908480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252A4C18A4F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20EB3DBD763F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63BE0E516D00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B38F7EE56CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755BBC2806FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506"
}
This commit is contained in:
Nicolas Williams
2021-02-23 21:52:41 -06:00
parent db7763ca7b
commit fb2c81f3e8
14 changed files with 1335 additions and 32 deletions

View File

@@ -6,7 +6,7 @@ YFLAGS = -d -t
AM_CPPFLAGS += $(ROKEN_RENAME)
man_MANS = asn1_compile.1
man_MANS = asn1_print.1 asn1_compile.1
lib_LTLIBRARIES = libasn1.la
libasn1_la_LDFLAGS = -version-info 8:0:0
@@ -109,6 +109,7 @@ dist_libasn1base_la_SOURCES = \
der_get.c \
der_put.c \
der_free.c \
der_print.c \
der_length.c \
der_copy.c \
der_cmp.c \
@@ -132,7 +133,7 @@ asn1_compile_LDADD = \
$(LIB_roken) $(LEXLIB)
check_der_LDADD = \
libasn1base.la \
libasn1.la \
$(LIB_roken)
check_template_LDADD = $(check_der_LDADD)

View File

@@ -116,6 +116,7 @@ LIBASN1_OBJS= \
$(OBJ)\der_get.obj \
$(OBJ)\der_put.obj \
$(OBJ)\der_free.obj \
$(OBJ)\der_print.obj \
$(OBJ)\der_length.obj \
$(OBJ)\der_copy.obj \
$(OBJ)\der_cmp.obj \
@@ -381,6 +382,7 @@ libasn1_base_SOURCES= \
der_get.c \
der_put.c \
der_free.c \
der_print.c \
der_length.c \
der_copy.c \
der_cmp.c \

View File

@@ -159,6 +159,55 @@ make it easy to add support for encoding rules other than X.690.
- Most of X.690 is supported for decoding, with only DER supported for
encoding.
- We have an `asn1_print` program that can decode DER from any exported types
from any ASN.1 modules committed in Heimdal:
```bash
$ ./asn1_print ek.crt Certificate |
jq '.tbsCertificate.extensions[3]._open_type[]._open_type'
```
```JSON
[
{
"_type": "TPMSpecification",
"family": "2.0",
"level": "0",
"revision": "138"
}
]
[
{
"_type": "TPMSecurityAssertions",
"version": "0",
"fieldUpgradable": "1",
"ekGenerationType": "655617",
"ekGenerationLocation": "655616",
"ekCertificateGenerationLocation": "655616",
"ccInfo": {
"_type": "CommonCriteriaMeasures",
"version": "3.1",
"assurancelevel": "4",
"evaluationStatus": "2",
"plus": "1",
"strengthOfFunction": null,
"profileOid": null,
"profileUri": null,
"targetOid": null,
"targetUri": null
},
"fipsLevel": {
"_type": "FIPSLevel",
"version": "140-2",
"level": "2",
"plus": "0"
},
"iso9000Certified": "0",
"iso9000Uri": null
}
]
```
- 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
@@ -183,6 +232,11 @@ make it easy to add support for encoding rules other than X.690.
## Limitations
- `asn1_print`'s JSON support is not X.697 (JER) compatible.
- Control over C types generated is very limited, mainly only for integer
types.
- When using the template backend, `SET { .. }` types are currently not sorted
by tag as they should be, but if the module author sorts them by hand then
DER will be produced.

View File

@@ -55,6 +55,10 @@ typedef struct heim_base_data heim_any_set;
typedef struct heim_base_data HEIM_ANY;
typedef struct heim_base_data HEIM_ANY_SET;
enum asn1_print_flags {
ASN1_PRINT_INDENT = 1,
};
#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \
do { \
(BL) = length_##T((S)); \

View File

@@ -118,9 +118,8 @@
* offset is all ones
*/
/* name: when it happens at index 1 it's the name of the SET/SEQUENCE/CHOICE
* when it happens at any other index it's the name of the field that the
* next entry deals with
/* name: first one is the name of the SET/SEQUENCE/CHOICE type
* subsequent ones are the name of the nth field
*
* 0..23 unused
* 24..27 flags A1_NM_*
@@ -218,6 +217,7 @@ typedef int (ASN1CALL *asn1_type_encode)(unsigned char *, size_t, const void *,
typedef size_t (ASN1CALL *asn1_type_length)(const void *);
typedef void (ASN1CALL *asn1_type_release)(void *);
typedef int (ASN1CALL *asn1_type_copy)(const void *, void *);
typedef char * (ASN1CALL *asn1_type_print)(const void *, int);
struct asn1_type_func {
asn1_type_encode encode;
@@ -225,6 +225,7 @@ struct asn1_type_func {
asn1_type_length length;
asn1_type_copy copy;
asn1_type_release release;
asn1_type_print print;
size_t size;
};
@@ -279,8 +280,10 @@ _asn1_copy_top (
void * /*to*/);
void
_asn1_free_top(const struct asn1_template *t,
void *data);
_asn1_free_top(const struct asn1_template *, void *);
char *
_asn1_print_top(const struct asn1_template *, int, const void *);
int
_asn1_decode_top (

View File

@@ -2182,9 +2182,184 @@ test_ios(void)
0xea, 0xa4, 0x2b, 0x6f, 0x56, 0x3d, 0xf7, 0xaa,
0x75, 0x06,
};
char cert_json[] = {
"{\"_type\":\"Certificate\",\"tbsCertificate\":{\"_type\":\"TBSCe"
"rtificate\",\"_save\":\"30820376A00302010202146A0597BA71D7E6D3AC"
"0EDC9EDC95A15B998DE40A300D06092A864886F70D01010B05003055310B3009"
"060355040613024348311E301C060355040A131553544D6963726F656C656374"
"726F6E696373204E56312630240603550403131D53544D2054504D20454B2049"
"6E7465726D656469617465204341203035301E170D3138313231343030303030"
"305A170D3238313231343030303030305A300030820122300D06092A864886F7"
"0D01010105000382010F003082010A0282010100CC14EB27A78CEB0EA486FA2D"
"F7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239F"
"A95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E78"
"6A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347"
"871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB"
"4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C7561"
"7047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D"
"198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D1"
"6891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001A38201A9308201"
"A5301F0603551D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C0"
"866030420603551D20043B303930370604551D2000302F302D06082B06010505"
"0702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F73"
"69746F72792F30590603551D110101FF044F304DA44B30493116301406056781"
"0502010C0B69643A353335343444323031173015060567810502020C0C535433"
"33485450484148433031163014060567810502030C0B69643A30303439303030"
"3830670603551D090460305E301706056781050210310E300C0C03322E300201"
"000202008A304306056781050212313A30380201000101FFA0030A0101A1030A"
"0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D160531"
"34302D320A0102010100300E0603551D0F0101FF040403020520300C0603551D"
"130101FF0402300030100603551D250409300706056781050801304A06082B06"
"010505070101043E303C303A06082B06010505073002862E687474703A2F2F73"
"65637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E74"
"30352E637274\",\"version\":\"2\",\"serialNumber\":\"6A0597BA71D7"
"E6D3AC0EDC9EDC95A15B998DE40A\",\"signature\":{\"_type\":\"Algori"
"thmIdentifier\",\"algorithm\":{\"_type\":\"OBJECT IDENTIFIER\",\""
"oid\":\"1.2.840.113549.1.1.11\",\"components\":[1,2,840,113549,"
"1,1,11],\"name\":\"id-pkcs1-sha256WithRSAEncryption\"},\"paramet"
"ers\":\"0500\"},\"issuer\":{\"_choice\":\"rdnSequence\",\"value\""
":[[{\"_type\":\"AttributeTypeAndValue\",\"type\":{\"_type\":\"O"
"BJECT IDENTIFIER\",\"oid\":\"2.5.4.6\",\"components\":[2,5,4,6],"
"\"name\":\"id-at-countryName\"},\"value\":{\"_choice\":\"printab"
"leString\",\"value\":\"CH\"}}],[{\"_type\":\"AttributeTypeAndVal"
"ue\",\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.4.1"
"0\",\"components\":[2,5,4,10],\"name\":\"id-at-organizationName\""
"},\"value\":{\"_choice\":\"printableString\",\"value\":\"STMicr"
"oelectronics NV\"}}],[{\"_type\":\"AttributeTypeAndValue\",\"typ"
"e\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.4.3\",\"compo"
"nents\":[2,5,4,3],\"name\":\"id-at-commonName\"},\"value\":{\"_c"
"hoice\":\"printableString\",\"value\":\"STM TPM EK Intermediate "
"CA 05\"}}]]},\"validity\":{\"_type\":\"Validity\",\"notBefore\":"
"{\"_choice\":\"utcTime\",\"value\":\"2018-12-14T00:00:00Z\"},\"n"
"otAfter\":{\"_choice\":\"utcTime\",\"value\":\"2028-12-14T00:00:"
"00Z\"}},\"subject\":{\"_choice\":\"rdnSequence\",\"value\":[]},\""
"subjectPublicKeyInfo\":{\"_type\":\"SubjectPublicKeyInfo\",\"al"
"gorithm\":{\"_type\":\"AlgorithmIdentifier\",\"algorithm\":{\"_t"
"ype\":\"OBJECT IDENTIFIER\",\"oid\":\"1.2.840.113549.1.1.1\",\"c"
"omponents\":[1,2,840,113549,1,1,1],\"name\":\"id-pkcs1-rsaEncryp"
"tion\"},\"parameters\":\"0500\"},\"subjectPublicKey\":\"2160:308"
"2010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BD"
"E50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87"
"352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B"
"58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5E"
"B271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF"
"0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E03250809"
"4FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C765"
"7414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F1"
"49744E5F0D559B10203010001\"},\"issuerUniqueID\":null,\"subjectUn"
"iqueID\":null,\"extensions\":[{\"_type\":\"Extension\",\"extnID\""
":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.29.35\",\"compo"
"nents\":[2,5,29,35],\"name\":\"id-x509-ce-authorityKeyIdentifier"
"\"},\"critical\":false,\"extnValue\":\"301680141ADB994AB58BE57A0"
"CC9B900E7851E1A43C08660\",\"_extnValue_choice\":\"ext-AuthorityK"
"eyIdentifier\",\"_extnValue\":{\"_type\":\"AuthorityKeyIdentifi"
"er\",\"keyIdentifier\":\"1ADB994AB58BE57A0CC9B900E7851E1A43C0866"
"0\",\"authorityCertIssuer\":null,\"authorityCertSerialNumber\":n"
"ull}},{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT ID"
"ENTIFIER\",\"oid\":\"2.5.29.32\",\"components\":[2,5,29,32],\"na"
"me\":\"id-x509-ce-certificatePolicies\"},\"critical\":false,\"ex"
"tnValue\":\"303930370604551D2000302F302D06082B060105050702011621"
"687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F7279"
"2F\",\"_extnValue_choice\":\"ext-CertificatePolicies\",\"_extnV"
"alue\":[{\"_type\":\"PolicyInformation\",\"policyIdentifier\":{\""
"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.29.32.0\",\"compone"
"nts\":[2,5,29,32,0],\"name\":\"id-x509-ce-certificatePolicies-an"
"yPolicy\"},\"policyQualifiers\":[{\"_type\":\"PolicyQualifierInf"
"o\",\"policyQualifierId\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid"
"\":\"1.3.6.1.5.5.7.2.1\",\"components\":[1,3,6,1,5,5,7,2,1],\"na"
"me\":\"id-pkix-qt-cps\"},\"qualifier\":\"1621687474703A2F2F77777"
"72E73742E636F6D2F54504D2F7265706F7369746F72792F\"}]}]},{\"_type\""
":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oi"
"d\":\"2.5.29.17\",\"components\":[2,5,29,17],\"name\":\"id-x509-"
"ce-subjectAltName\"},\"critical\":true,\"extnValue\":\"304DA44B3"
"04931163014060567810502010C0B69643A35333534344432303117301506056"
"7810502020C0C53543333485450484148433031163014060567810502030C0B6"
"9643A3030343930303038\",\"_extnValue_choice\":\"ext-SubjectAltNa"
"me\",\"_extnValue\":[{\"_choice\":\"directoryName\",\"value\":{"
"\"_choice\":\"rdnSequence\",\"value\":[[{\"_type\":\"AttributeTy"
"peAndValue\",\"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\",\"ty"
"pe\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.2\",\""
"components\":[2,23,133,2,2],\"name\":\"tcg-at-tpmModel\"},\"val"
"ue\":{\"_choice\":\"utf8String\",\"value\":\"ST33HTPHAHC0\"}}],["
"{\"_type\":\"AttributeTypeAndValue\",\"type\":{\"_type\":\"OBJEC"
"T IDENTIFIER\",\"oid\":\"2.23.133.2.3\",\"components\":[2,23,133"
",2,3],\"name\":\"tcg-at-tpmVersion\"},\"value\":{\"_choice\":\"u"
"tf8String\",\"value\":\"id:00490008\"}}]]}}]},{\"_type\":\"Exten"
"sion\",\"extnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5"
".29.9\",\"components\":[2,5,29,9],\"name\":\"id-x509-ce-subjectD"
"irectoryAttributes\"},\"critical\":false,\"extnValue\":\"305E301"
"706056781050210310E300C0C03322E300201000202008A30430605678105021"
"2313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E16033"
"32E310A01040A01020101FFA40F300D16053134302D320A0102010100\",\"_e"
"xtnValue_choice\":\"ext-SubjectDirectoryAttributes\",\"_extnVal"
"ue\":[{\"_type\":\"AttributeSet\",\"type\":{\"_type\":\"OBJECT I"
"DENTIFIER\",\"oid\":\"2.23.133.2.16\",\"components\":[2,23,133,2"
",16],\"name\":\"tcg-at-tpmSpecification\"},\"values\":[\"300C0C0"
"3322E300201000202008A\"],\"_values_choice\":\"at-TPMSpecificatio"
"n\",\"_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-tpmSecurit"
"yAssertions\"},\"values\":[\"30380201000101FFA0030A0101A1030A010"
"0A2030A0100A310300E1603332E310A01040A01020101FFA40F300D160531343"
"02D320A0102010100\"],\"_values_choice\":\"at-TPMSecurityAssertio"
"ns\",\"_values\":[{\"_type\":\"TPMSecurityAssertions\",\"versio"
"n\":\"0\",\"fieldUpgradable\":true,\"ekGenerationType\":\"655617"
"\",\"ekGenerationLocation\":\"655616\",\"ekCertificateGeneration"
"Location\":\"655616\",\"ccInfo\":{\"_type\":\"CommonCriteriaMeas"
"ures\",\"version\":\"3.1\",\"assurancelevel\":\"4\",\"evaluation"
"Status\":\"2\",\"plus\":true,\"strengthOfFunction\":null,\"profi"
"leOid\":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\":tr"
"ue,\"extnValue\":\"03020520\",\"_extnValue_choice\":\"ext-KeyUsa"
"ge\",\"_extnValue\":[\"keyEncipherment\"]},{\"_type\":\"Extensi"
"on\",\"extnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.2"
"9.19\",\"components\":[2,5,29,19],\"name\":\"id-x509-ce-basicCon"
"straints\"},\"critical\":true,\"extnValue\":\"3000\",\"_extnValu"
"e_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\":\"i"
"d-x509-ce-extKeyUsage\"},\"critical\":false,\"extnValue\":\"3007"
"06056781050801\",\"_extnValue_choice\":\"ext-ExtKeyUsage\",\"_e"
"xtnValue\":[{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133."
"8.1\",\"components\":[2,23,133,8,1],\"name\":\"tcg-kp-EKCertific"
"ate\"}]},{\"_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\"},\"cr"
"itical\":false,\"extnValue\":\"303C303A06082B06010505073002862E6"
"87474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D7"
"4706D656B696E7430352E637274\",\"_extnValue_choice\":\"ext-Author"
"ityInfoAccess\",\"_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\":\"unif"
"ormResourceIdentifier\",\"value\":\"http://secure.globalsign.com"
"/stmtpmekint05.crt\"}}]}]},\"signatureAlgorithm\":{\"_type\":\"A"
"lgorithmIdentifier\",\"algorithm\":{\"_type\":\"OBJECT IDENTIFIE"
"R\",\"oid\":\"1.2.840.113549.1.1.11\",\"components\":[1,2,840,11"
"3549,1,1,11],\"name\":\"id-pkcs1-sha256WithRSAEncryption\"},\"pa"
"rameters\":\"0500\"},\"signatureValue\":\"2048:3D4C381E5B4F1BCBE"
"09C63D52F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF88690130"
"41E92CDD3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAF"
"F9E7E908480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252"
"A4C18A4F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20"
"EB3DBD763F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63B"
"E0E516D00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B3"
"8F7EE56CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755"
"BBC2806FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506\"}"
};
heim_octet_string os;
Certificate c0, c1;
size_t i, nknown, size;
char *s;
int ret;
/*
@@ -2200,6 +2375,13 @@ test_ios(void)
if (size != sizeof(encoded_sample))
return 1;
s = print_Certificate(&c0, 0);
if (!s)
return 1;
if (strcmp(s, cert_json))
return 1;
free(s);
ret = copy_Certificate(&c0, &c1);
if (ret)
return 1;
@@ -2225,6 +2407,7 @@ test_ios(void)
if (!nknown)
return 1;
/*
* Check that this round trips. But note that this attempt to encode will
* ignore the automatically decoded open type values from above because
@@ -2272,7 +2455,6 @@ test_ios(void)
return 1;
der_free_octet_string(&os);
/* XXX Test setting some of the _ioschoice_extnValue._element's to 0 */
free_Certificate(&c0);
free_Certificate(&c1);
return 0;

227
lib/asn1/der_print.c Normal file
View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 2021 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Portions Copyright (c) 2009 Apple Inc. 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.
*/
#include "der_locl.h"
#include "hex.h"
RCSID("$Id$");
char *
der_print_general_string(const heim_general_string *str, int flags)
{
return strdup(*str);
}
char *
der_print_boolean(const int *i, int flags)
{
return *i ? strdup("true") : strdup("false");
}
char *
der_print_integer(const int *i, int flags)
{
char *s = NULL;
if (asprintf(&s, "%d", *i) == -1 || s == NULL)
return NULL;
return s;
}
char *
der_print_integer64(const int64_t *i, int flags)
{
char *s = NULL;
if (asprintf(&s, "%lld", (long long)*i) == -1 || s == NULL)
return NULL;
return s;
}
char *
der_print_unsigned(const unsigned *u, int flags)
{
char *s = NULL;
if (asprintf(&s, "%u", *u) == -1 || s == NULL)
return NULL;
return s;
}
char *
der_print_unsigned64(const uint64_t *u, int flags)
{
char *s = NULL;
if (asprintf(&s, "%llu", (long long)*u) == -1 || s == NULL)
return NULL;
return s;
}
char *
der_print_generalized_time(const time_t *t, int flags)
{
struct tm tms;
char str[sizeof("1970-01-01T00:00:00Z")];
#ifdef WIN32
if (strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", gmtime_s(&tms, t)) == 0)
return NULL;
#else
if (strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", gmtime_r(t, &tms)) == 0)
return NULL;
#endif
return strdup(str);
}
char *
der_print_utctime(const time_t *t, int flags)
{
struct tm tms;
char str[sizeof("1970-01-01T00:00:00Z")];
#ifdef WIN32
if (strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", gmtime_s(&tms, t)) == 0)
return NULL;
#else
if (strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", gmtime_r(t, &tms)) == 0)
return NULL;
#endif
return strdup(str);
}
char *
der_print_utf8string(const heim_utf8_string *str, int flags)
{
return strdup(*str);
}
char *
der_print_printable_string(const heim_printable_string *str, int flags)
{
return strndup(str->data, str->length);
}
char *
der_print_ia5_string(const heim_ia5_string *str, int flags)
{
return strndup(str->data, str->length);
}
char *
der_print_bmp_string(const heim_bmp_string *k, int flags)
{
return strdup("<BMPString-not-supported>");
}
char *
der_print_universal_string(const heim_universal_string *k, int flags)
{
return strdup("<UniversalString-not-supported>");
}
char *
der_print_visible_string(const heim_visible_string *str, int flags)
{
return strdup(*str);
}
char *
der_print_octet_string(const heim_octet_string *k, int flags)
{
char *s = NULL;
(void) hex_encode(k->data, k->length, &s);
return s;
}
char *
der_print_heim_integer(const heim_integer *k, int flags)
{
char *s = NULL;
(void) der_print_hex_heim_integer(k, &s);
return s;
}
char *
der_print_oid(const heim_oid *k, int flags)
{
struct rk_strpool *r = NULL;
const char *sym = NULL;
char *s = NULL;
size_t i;
(void) der_print_heim_oid(k, '.', &s);
if (!s)
return NULL;
r = rk_strpoolprintf(r, "{\"_type\":\"OBJECT IDENTIFIER\","
"\"oid\":\"%s\","
"\"components\":[",
s);
free(s);
for (i = 0; i < k->length; i++)
r = rk_strpoolprintf(r, "%s%u", i ? "," : "", k->components[i]);
if (r)
r = rk_strpoolprintf(r, "]");
(void) der_find_heim_oid_by_oid(k, &sym);
if (sym && r) {
if ((s = strdup(sym))) {
for (i = 0; s[i]; i++)
if (s[i] == '_')
s[i] = '-';
}
r = rk_strpoolprintf(r, ",\"name\":\"%s\"", s ? s : sym);
free(s);
}
if (r)
r = rk_strpoolprintf(r, "}");
return rk_strpoolcollect(r);
}
char *
der_print_bit_string(const heim_bit_string *k, int flags)
{
char *s2 = NULL;
char *s = NULL;
(void) hex_encode(k->data, k->length / 8, &s);
if (asprintf(&s2, "%llu:%s", (unsigned long long)k->length, s) == -1 || !s2)
return NULL;
free(s);
return s2;
}

View File

@@ -90,6 +90,12 @@ free_heim_any(heim_any *data)
der_free_octet_string(data);
}
char *
print_heim_any(const heim_any *data)
{
return der_print_octet_string(data, 0);
}
size_t
length_heim_any(const heim_any *data)
{
@@ -122,6 +128,12 @@ free_HEIM_ANY(heim_any *data)
der_free_octet_string(data);
}
char *
print_HEIM_ANY(const heim_any *data)
{
return der_print_octet_string(data, 0);
}
size_t
length_HEIM_ANY(const heim_any *data)
{
@@ -154,6 +166,12 @@ free_heim_any_set(heim_any_set *data)
der_free_octet_string(data);
}
char *
print_heim_any_set(const heim_any_set *data)
{
return der_print_octet_string(data, 0);
}
size_t
length_heim_any_set(const heim_any *data)
{
@@ -192,6 +210,12 @@ free_HEIM_ANY_SET(heim_any_set *data)
der_free_octet_string(data);
}
char *
print_HEIM_ANY_SET(const heim_any_set *data)
{
return der_print_octet_string(data, 0);
}
size_t
length_HEIM_ANY_SET(const heim_any *data)
{

View File

@@ -237,6 +237,11 @@ init_generate (const char *filename, const char *base)
"typedef struct heim_base_data heim_any_set;\n"
"typedef struct heim_base_data HEIM_ANY;\n"
"typedef struct heim_base_data HEIM_ANY_SET;\n\n");
fprintf (headerfile,
"enum asn1_print_flags {\n"
" ASN1_PRINT_INDENT = 1,\n"
"};\n\n");
fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
" do { \\\n"
" (BL) = length_##T((S)); \\\n"
@@ -1675,6 +1680,12 @@ generate_type (const Symbol *s)
exp,
s->gen_name, s->gen_name);
if (template_flag)
fprintf(h,
"%schar * ASN1CALL print_%s (const %s *, int);\n",
exp,
s->gen_name, s->gen_name);
fprintf(h, "\n\n");
if (!one_code_file) {

View File

@@ -295,6 +295,8 @@ static int tlist_cmp(const struct tlist *, const struct tlist *);
static void add_line_pointer(struct templatehead *, const char *, const char *, const char *, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
static void add_line_string(struct templatehead *, const char *, const char *, const char *, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
static void add_line_pointer_reference(struct templatehead *, const char *, const char *, const char *, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
@@ -384,6 +386,8 @@ tlist_cmp(const struct tlist *tl, const struct tlist *ql)
int ret;
struct template *t, *q;
if (tl == ql)
return 0;
ret = strcmp(tl->header, ql->header);
if (ret) return ret;
@@ -470,6 +474,28 @@ add_line_pointer(struct templatehead *t,
q->ptr = strdup(ptr);
}
static void
add_line_string(struct templatehead *t,
const char *str,
const char *offset,
const char *ttfmt,
...)
{
struct template *q;
va_list ap;
char *tt = NULL;
va_start(ap, ttfmt);
if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
errx(1, "malloc");
va_end(ap);
q = add_line(t, "{ %s, %s, \"%s\" }", tt, offset, str);
q->tt = tt;
q->offset = strdup(offset);
q->ptr = strdup(str);
}
static void
add_line_pointer_reference(struct templatehead *t,
const char *ptr,
@@ -755,6 +781,7 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
sort_object_set(os, typeidfield, &objects, &nobjs);
tl = tlist_new(os->symbol->name);
add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", os->symbol->name);
for (i = 0; i < nobjs; i++) {
ObjectField *typeidobjf = NULL, *opentypeobjf = NULL;
ObjectField *of;
@@ -777,6 +804,7 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
continue;
}
add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", o->symbol->name);
/*
* Some of this logic could stand to move into sanity checks of object
* definitions in asn1parse.y.
@@ -849,6 +877,17 @@ template_open_type(struct templatehead *temp,
free(s);
}
static void
template_names(struct templatehead *temp, const char *basetype, const Type *t)
{
Member *m;
add_line_string(temp, basetype, "0", "A1_OP_NAME");
HEIM_TAILQ_FOREACH(m, t->members, members) {
add_line_string(temp, m->name, "0", "A1_OP_NAME");
}
}
static void
template_members(struct templatehead *temp,
const char *basetype,
@@ -968,7 +1007,7 @@ template_members(struct templatehead *temp,
output_name(bname);
HEIM_TAILQ_FOREACH(m, t->members, members) {
add_line(&template, "{ 0, %d, 0 } /* %s */", m->val, m->gen_name);
add_line(&template, "{ 0, %d, \"%s\" }", m->val, m->gen_name);
}
HEIM_TAILQ_FOREACH(q, &template, members) {
@@ -1038,6 +1077,9 @@ template_members(struct templatehead *temp,
template_open_type(temp, basetype, t, typeididx, opentypeidx,
typeidfield, opentypefield, opentypemember,
is_array_of_open_type);
if (isstruct)
template_names(temp, basetype, t);
break;
}
case TSequence: {
@@ -1086,6 +1128,9 @@ template_members(struct templatehead *temp,
template_open_type(temp, basetype, t, typeididx, opentypeidx,
typeidfield, opentypefield, opentypemember,
is_array_of_open_type);
if (isstruct)
template_names(temp, basetype, t);
break;
}
case TTag: {
@@ -1233,6 +1278,10 @@ template_members(struct templatehead *temp,
free(newbasename);
}
HEIM_TAILQ_FOREACH(m, t->members, members) {
add_line(&template, "{ 0, 0, \"%s\" }", m->name);
}
e = NULL;
if (ellipsis) {
if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)
@@ -1276,10 +1325,11 @@ gen_extern_stubs(FILE *f, const char *name)
"\t(asn1_type_length)length_%s,\n"
"\t(asn1_type_copy)copy_%s,\n"
"\t(asn1_type_release)free_%s,\n"
"\t(asn1_type_print)print_%s,\n"
"\tsizeof(%s)\n"
"};\n",
name, name, name, name,
name, name, name);
name, name, name, name);
}
void
@@ -1463,4 +1513,16 @@ generate_template(const Symbol *s)
s->gen_name,
s->gen_name,
dupname);
fprintf(f,
"\n"
"char *\n"
"print_%s(const %s *data, int flags)\n"
"{\n"
" return _asn1_print_top(asn1_%s, flags, data);\n"
"}\n"
"\n",
s->gen_name,
s->gen_name,
dupname);
}

View File

@@ -37,6 +37,7 @@
int encode_heim_any(unsigned char *, size_t, const heim_any *, size_t *);
int decode_heim_any(const unsigned char *, size_t, heim_any *, size_t *);
void free_heim_any(heim_any *);
char *print_heim_any(const heim_any *);
size_t length_heim_any(const heim_any *);
int copy_heim_any(const heim_any *, heim_any *);
@@ -45,6 +46,7 @@ int encode_heim_any_set(unsigned char *, size_t,
int decode_heim_any_set(const unsigned char *, size_t,
heim_any_set *,size_t *);
void free_heim_any_set(heim_any_set *);
char *print_heim_any_set(const heim_any_set *);
size_t length_heim_any_set(const heim_any_set *);
int copy_heim_any_set(const heim_any_set *, heim_any_set *);
int heim_any_cmp(const heim_any_set *, const heim_any_set *);
@@ -52,6 +54,7 @@ int heim_any_cmp(const heim_any_set *, const heim_any_set *);
int encode_HEIM_ANY(unsigned char *, size_t, const heim_any *, size_t *);
int decode_HEIM_ANY(const unsigned char *, size_t, heim_any *, size_t *);
void free_HEIM_ANY(heim_any *);
char *print_HEIM_ANY(const heim_any *);
size_t length_HEIM_ANY(const heim_any *);
int copy_HEIM_ANY(const heim_any *, heim_any *);
@@ -60,6 +63,7 @@ int encode_HEIM_ANY_SET(unsigned char *, size_t,
int decode_HEIM_ANY_SET(const unsigned char *, size_t,
heim_any_set *,size_t *);
void free_HEIM_ANY_SET(heim_any_set *);
char *print_HEIM_ANY_SET(const heim_any_set *);
size_t length_HEIM_ANY_SET(const heim_any_set *);
int copy_HEIM_ANY_SET(const heim_any_set *, heim_any_set *);
int heim_any_cmp(const heim_any_set *, const heim_any_set *);

View File

@@ -2221,6 +2221,360 @@ EXPORTS
length_X690SampleEmployeeNumber
length_X690SampleName
length_X690SamplePersonnelRecord
print_AccessDescription
print_AD_AND_OR
print_AD_IF_RELEVANT
print_AD_INITIAL_VERIFIED_CAS
print_AD_KDCIssued
print_AD_LoginAlias
print_AD_MANDATORY_FOR_KDC
print_AlgorithmIdentifier
print_AliasIA5String
print_AliasPrintableString
print_AliasUTF8String
print_APOptions
print_AP_REP
print_AP_REQ
print_AS_REP
print_AS_REQ
print_Attribute
print_AttributeSet
print_AttributeType
print_AttributeTypeAndValue
print_AttributeValue
print_AttributeValues
print_AUTHDATA_TYPE
print_Authenticator
print_AuthorityInfoAccessSyntax
print_AuthorityKeyIdentifier
print_AuthorizationData
print_AuthorizationDataElement
print_AuthPack
print_AuthPack_Win2k
print_BaseDistance
print_BasicConstraints
print_Certificate
print_CertificateList
print_CertificatePolicies
print_CertificateRevocationLists
print_Certificates
print_CertificateSerialNumber
print_CertificateSet
print_CertificationRequest
print_CertificationRequestInfo
print_CertPolicyId
print_ChangePasswdDataMS
print_Checksum
print_CKSUMTYPE
print_CMSAttributes
print_CMSCBCParameter
print_CMSEncryptedData
print_CMSIdentifier
print_CMSRC2CBCParameter
print_CMSVersion
print_CommonCriteriaMeasures
print_CommunityIdentifier
print_CommunityIdentifiers
print_ContentEncryptionAlgorithmIdentifier
print_ContentInfo
print_ContentType
print_CPSuri
print_CRLCertificateList
print_CRLDistributionPoints
print_CRLReason
print_CurrentFWConfig
print_DecryptKeyIdentifier
print_DHNonce
print_DHParameter
print_DHPublicKey
print_DHRepInfo
print_DigestAlgorithmIdentifier
print_DigestAlgorithmIdentifiers
print_DigestError
print_DigestInfo
print_DigestInit
print_DigestInitReply
print_DigestREP
print_DigestRepInner
print_DigestREQ
print_DigestReqInner
print_DigestRequest
print_DigestResponse
print_DigestTypes
print_DirectoryString
print_DisplayText
print_DistributionPoint
print_DistributionPointName
print_DistributionPointReasonFlags
print_DomainParameters
print_DSAParams
print_DSAPublicKey
print_DSASigValue
print_ECDSA_Sig_Value
print_ECParameters
print_ECPoint
print_EKCertificateGenerationLocation
print_EKGenerationLocation
print_EKGenerationType
print_EncAPRepPart
print_EncapsulatedContentInfo
print_EncASRepPart
print_EncKDCRepPart
print_EncKrbCredPart
print_EncKrbPrivPart
print_EncryptedContent
print_EncryptedContentInfo
print_EncryptedData
print_EncryptedKey
print_EncryptionKey
print_EncTGSRepPart
print_EncTicketPart
print_ENCTYPE
print_EnvelopedData
print_ETYPE_INFO
print_ETYPE_INFO2
print_ETYPE_INFO2_ENTRY
print_ETYPE_INFO_ENTRY
print_EtypeList
print_EvaluationAssuranceLevel
print_EvaluationStatus
print_Extension
print_Extensions
print_ExternalPrincipalIdentifier
print_ExternalPrincipalIdentifiers
print_ExtKeyUsage
print_FastOptions
print_FIPSLevel
print_FirmwarePackageIdentifier
print_FirmwarePackageInfo
print_FirmwarePackageLoadError
print_FirmwarePackageLoadErrorCode
print_FirmwarePackageLoadReceipt
print_FirmwarePkgData
print_FWErrorVersion
print_FWReceiptVersion
print_GeneralName
print_GeneralNames
print_GeneralSubtree
print_GeneralSubtrees
print_HardwareModuleName
print_HardwareModules
print_HardwareSerialEntry
print_heim_any
print_HEIM_ANY
print_heim_any_set
print_HEIM_ANY_SET
print_HostAddress
print_HostAddresses
print_ImplementedCompressAlgorithms
print_ImplementedCryptoAlgorithms
print_IssuerAndSerialNumber
print_KDCDHKeyInfo
print_KDCDHKeyInfo_Win2k
print_KDCFastCookie
print_KDCFastFlags
print_KDCFastState
print_KDCOptions
print_KDC_PROXY_MESSAGE
print_KDC_REP
print_KDC_REQ
print_KDC_REQ_BODY
print_KDFAlgorithmId
print_KERB_ARMOR_SERVICE_REPLY
print_KERB_CRED
print_KerberosString
print_KerberosTime
print_KERB_TGS_REP_IN
print_KERB_TGS_REP_OUT
print_KERB_TGS_REQ_IN
print_KERB_TGS_REQ_OUT
print_KERB_TIMES
print_KeyEncryptionAlgorithmIdentifier
print_KeyIdentifier
print_KeyTransRecipientInfo
print_KeyUsage
print_Krb5Int32
print_KRB5PrincipalName
print_KRB5SignedPath
print_KRB5SignedPathData
print_Krb5UInt32
print_KRB_CRED
print_KrbCredInfo
print_KRB_ERROR
print_KrbFastArmor
print_KrbFastArmoredRep
print_KrbFastArmoredReq
print_KrbFastFinished
print_KrbFastReq
print_KrbFastResponse
print_KRB_PRIV
print_KRB_SAFE
print_KRB_SAFE_BODY
print_Kx509CSRPlus
print_Kx509ErrorCode
print_KX509_ERROR_CODE
print_Kx509Request
print_Kx509Response
print_LastReq
print_LR_TYPE
print_MessageDigest
print_MESSAGE_TYPE
print_METHOD_DATA
print_MS_UPN_SAN
print_Name
print_NameConstraints
print_NAME_TYPE
print_NoticeReference
print_NTLMInit
print_NTLMInitReply
print_NTLMReply
print_NTLMRequest
print_NTLMRequest2
print_NTLMResponse
print_OCSPBasicOCSPResponse
print_OCSPCertID
print_OCSPCertStatus
print_OCSPInnerRequest
print_OCSPKeyHash
print_OCSPRequest
print_OCSPResponderID
print_OCSPResponse
print_OCSPResponseBytes
print_OCSPResponseData
print_OCSPResponseStatus
print_OCSPSignature
print_OCSPSingleResponse
print_OCSPTBSRequest
print_OCSPVersion
print_OriginatorInfo
print_OtherName
print_PA_DATA
print_PADATA_TYPE
print_PA_ENC_SAM_RESPONSE_ENC
print_PA_ENC_TS_ENC
print_PA_FX_FAST_REPLY
print_PA_FX_FAST_REQUEST
print_PA_PAC_REQUEST
print_PA_PK_AS_REP
print_PA_PK_AS_REP_BTMM
print_PA_PK_AS_REP_Win2k
print_PA_PK_AS_REQ
print_PA_PK_AS_REQ_Win2k
print_PA_S4U2Self
print_PA_SAM_CHALLENGE_2
print_PA_SAM_CHALLENGE_2_BODY
print_PA_SAM_REDIRECT
print_PA_SAM_RESPONSE_2
print_PA_SAM_TYPE
print_PA_ServerReferralData
print_PA_SERVER_REFERRAL_DATA
print_PA_SvrReferralData
print_PermanentIdentifier
print_PKAuthenticator
print_PKAuthenticator_Win2k
print_PKCS12_Attribute
print_PKCS12_Attributes
print_PKCS12_AuthenticatedSafe
print_PKCS12_CertBag
print_PKCS12_MacData
print_PKCS12_OctetString
print_PKCS12_PBEParams
print_PKCS12_PFX
print_PKCS12_SafeBag
print_PKCS12_SafeContents
print_PKCS8Attributes
print_PKCS8EncryptedData
print_PKCS8EncryptedPrivateKeyInfo
print_PKCS8PrivateKey
print_PKCS8PrivateKeyAlgorithmIdentifier
print_PKCS8PrivateKeyInfo
print_PKCS9_BMPString
print_PKCS9_friendlyName
print_PkinitSP80056AOtherInfo
print_PkinitSuppPubInfo
print_PKIXXmppAddr
print_PolicyConstraints
print_PolicyInformation
print_PolicyMapping
print_PolicyMappings
print_PolicyQualifierId
print_PolicyQualifierInfo
print_PolicyQualifierInfos
print_PreferredOrLegacyPackageIdentifier
print_PreferredOrLegacyStalePackageIdentifier
print_PreferredPackageIdentifier
print_Principal
print_PrincipalName
print_Principals
print_PrivateKeyUsagePeriod
print_PROV_SRV_LOCATION
print_ProxyCertInfo
print_ProxyPolicy
print_RDNSequence
print_Realm
print_RecipientIdentifier
print_RecipientInfo
print_RecipientInfos
print_RelativeDistinguishedName
print_ReplyKeyPack
print_ReplyKeyPack_Win2k
print_RSAPrivateKey
print_RSAPublicKey
print_SAMFlags
print_SecurityLevel
print_SignatureAlgorithmIdentifier
print_SignatureValue
print_SignedData
print_SignerIdentifier
print_SignerInfo
print_SignerInfos
print_SingleAttribute
print_SkipCerts
print_SRVName
print_StrengthOfFunction
print_SubjectDirectoryAttributes
print_SubjectInfoAccessSyntax
print_SubjectKeyIdentifier
print_SubjectPublicKeyInfo
print_TargetHardwareIdentifiers
print_TBSCertificate
print_TBSCRLCertList
print_TD_DH_PARAMETERS
print_TD_INVALID_CERTIFICATES
print_TD_TRUSTED_CERTIFIERS
print_TGS_REP
print_TGS_REQ
print_Ticket
print_TicketFlags
print_Time
print_TPMSecurityAssertions
print_TPMSpecification
print_TPMVersion
print_TransitedEncoding
print_TrustedCA
print_TrustedCA_Win2k
print_TypedData
print_TYPED_DATA
print_UniqueIdentifier
print_UnprotectedAttributes
print_URIReference
print_UserNotice
print_ValidationParms
print_Validity
print_VendorLoadErrorCode
print_Version
print_WrappedFirmwareKey
print_X520CommonName
print_X520LocalityName
print_X520name
print_X520OrganizationalUnitName
print_X520OrganizationName
print_X520StateOrProvinceName
print_X690SampleChildInformation
print_X690SampleDate
print_X690SampleEmployeeNumber
print_X690SampleName
print_X690SamplePersonnelRecord
remove_AttributeValues
remove_AuthorizationData
remove_CertificatePolicies

View File

@@ -319,6 +319,7 @@ der_print_heim_oid_sym(const heim_oid *oid, char delim, char **strp)
const char *sym;
char *s1 = NULL;
char *s2 = NULL;
char *p;
int ret;
if (der_find_heim_oid_by_oid(oid, &sym))
@@ -330,6 +331,11 @@ der_print_heim_oid_sym(const heim_oid *oid, char delim, char **strp)
*strp = s1;
return 0;
}
p = s2 + strlen(s1) + 1;
for (p = s2 + strlen(s1) + 1; *p; p++) {
if (*p == '_')
*p = '-';
}
*strp = s2;
free(s1);
return 0;

View File

@@ -35,6 +35,7 @@
#include "der_locl.h"
#include <com_err.h>
#include <vis.h>
struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
#define el(name, type) { \
@@ -43,6 +44,7 @@ struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
(asn1_type_length)der_length_##name, \
(asn1_type_copy)der_copy_##name, \
(asn1_type_release)der_free_##name, \
(asn1_type_print)der_print_##name, \
sizeof(type) \
}
#define elber(name, type) { \
@@ -51,6 +53,7 @@ struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
(asn1_type_length)der_length_##name, \
(asn1_type_copy)der_copy_##name, \
(asn1_type_release)der_free_##name, \
(asn1_type_print)der_print_##name, \
sizeof(type) \
}
el(integer, int),
@@ -73,7 +76,8 @@ struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
el(bit_string, heim_bit_string),
{ (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean,
(asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer,
(asn1_type_release)der_free_integer, sizeof(int)
(asn1_type_release)der_free_integer, (asn1_type_print)der_print_boolean,
sizeof(int)
},
el(oid, heim_oid),
el(general_string, heim_general_string),
@@ -524,16 +528,23 @@ _asn1_decode_open_type(const struct asn1_template *t,
* An object set template looks like:
*
* const struct asn1_template asn1_ObjectSetName[] = {
* { 0, 0, ((void*)17) }, // HEADER ENTRY, here 17 objects
* // then two entries per object:
* // Header entry (in this case it says there's 17 objects):
* { 0, 0, ((void*)17) },
*
* // here's the name of the object set:
* { A1_OP_NAME, 0, "ObjectSetName" },
*
* // then three entries per object: object name, object type ID,
* // object type:
* { A1_OP_NAME, 0, "ext-AuthorityInfoAccess" },
* { A1_OP_OPENTYPE_ID, 0, (const void*)&asn1_oid_oidName },
* { A1_OP_OPENTYPE, sizeof(SomeType), (const void*)&asn1_SomeType },
* ...
* };
*
* `i' will be a logical object offset, so i*2+1 will be the index of the
* A1_OP_OPENTYPE_ID entry for the current object, and i*2+2 will be the
* index of the A1_OP_OPENTYPE entry for the current object.
* `i' being a logical object offset, i*3+3 would be the index of the
* A1_OP_OPENTYPE_ID entry for the current object, and i*3+4 the index of
* the A1_OP_OPENTYPE entry for the current object.
*/
if (t->tt & A1_OS_IS_SORTED) {
size_t left = 0;
@@ -544,13 +555,13 @@ _asn1_decode_open_type(const struct asn1_template *t,
while (left <= right) {
size_t mid = (left + right) >> 1;
if ((tos[1 + mid * 2].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
if ((tos[3 + mid * 3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
return 0;
if (typeid_is_int)
c = typeid_int_cmp(vp, (intptr_t)tos[1 + mid * 2].ptr,
c = typeid_int_cmp(vp, (intptr_t)tos[3 + mid * 3].ptr,
ttypeid_univ);
else if (typeid_is_oid)
c = der_heim_oid_cmp(vp, tos[1 + mid * 2].ptr);
c = der_heim_oid_cmp(vp, tos[3 + mid * 3].ptr);
if (c < 0) {
if (mid)
right = mid - 1;
@@ -568,15 +579,15 @@ _asn1_decode_open_type(const struct asn1_template *t,
} else {
for (i = 0, n = A1_HEADER_LEN(tos); i < n; i++) {
/* We add 1 to `i' because we're skipping the header */
if ((tos[1 + i*2].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
if ((tos[3 + i*3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
return 0;
if (typeid_is_int &&
typeid_int_cmp(DPO(data, ttypeid->offset),
(intptr_t)tos[1 + i*2].ptr,
(intptr_t)tos[3 + i*3].ptr,
ttypeid_univ))
continue;
if (typeid_is_oid &&
der_heim_oid_cmp(DPO(data, ttypeid->offset), tos[1 + i*2].ptr))
der_heim_oid_cmp(DPO(data, ttypeid->offset), tos[3 + i*3].ptr))
continue;
break;
}
@@ -592,7 +603,7 @@ _asn1_decode_open_type(const struct asn1_template *t,
* the object we'll be decoding into, and its `ptr' is the pointer to the
* template for decoding that type.
*/
tactual_type = &tos[i*2 + 2];
tactual_type = &tos[i*3 + 4];
/* Decode the encoded open type value(s) */
if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
@@ -1074,7 +1085,7 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
*/
*element = 1;
for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) {
for (i = 1; i < A1_HEADER_LEN(choice) + 1 && choice[i].tt; i++) {
/*
* This is more permissive than is required. CHOICE
* alternatives must have different outer tags, so in principle
@@ -1102,10 +1113,11 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
return ret;
}
}
if (i >= A1_HEADER_LEN(choice) + 1) {
if (i >= A1_HEADER_LEN(choice) + 1 || !choice[i].tt) {
if (choice->tt == 0)
return ASN1_BAD_ID;
/* This is the ellipsis case */
*element = 0;
ret = der_get_octet_string(p, len,
DPO(data, choice->tt), &datalen);
@@ -1261,13 +1273,13 @@ _asn1_encode_open_type(const struct asn1_template *t,
* field.
*/
ret = typeid_int_copy(DPO(data, ttypeid->offset),
(intptr_t)tos[1 + (element-1)*2].ptr, ttypeid_univ);
(intptr_t)tos[3 + (element-1)*3].ptr, ttypeid_univ);
} else if (typeid_is_oid) {
/*
* Copy the OID from the type ID object field to the type ID struct
* field.
*/
ret = der_copy_oid(tos[1 + (element-1)*2].ptr, DPO(data, ttypeid->offset));
ret = der_copy_oid(tos[3 + (element-1)*3].ptr, DPO(data, ttypeid->offset));
} else
enotsup = 1;
@@ -1278,7 +1290,7 @@ _asn1_encode_open_type(const struct asn1_template *t,
if (enotsup)
return ENOTSUP;
tactual_type = &tos[(element-1)*2 + 2];
tactual_type = &tos[(element-1)*3 + 4];
if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
struct heim_base_data *os = DPO(data, topentype->offset);
@@ -1861,11 +1873,11 @@ _asn1_length_open_type(const struct asn1_template *tbase,
} else if (typeid_is_oid) {
heim_oid no_oid = { 0, 0 };
sz = _asn1_length_open_type_id(ttypeid, tos[1 + (element - 1)*2].ptr);
sz = _asn1_length_open_type_id(ttypeid, tos[3 + (element - 1)*3].ptr);
sz -= _asn1_length_open_type_id(ttypeid, &no_oid);
}
tactual_type = &tos[(element-1)*2 + 2];
tactual_type = &tos[(element-1)*3 + 4];
/* Compute the size of the encoded value(s) */
if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
@@ -2126,7 +2138,7 @@ _asn1_free_open_type(const struct asn1_template *t, /* object set template */
/* XXX We assume sizeof(enum) == sizeof(int) */
if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1)
return; /* Unknown choice -> it's not decoded, nothing to free here */
tactual_type = tos[2*(*elementp - 1) + 2].ptr;
tactual_type = tos[3*(*elementp - 1) + 4].ptr;
if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
dp = DPO(data, t->offset + sizeof(*elementp));
@@ -2271,6 +2283,363 @@ _asn1_free(const struct asn1_template *t, void *data)
}
}
static char *
getindent(int flags, unsigned int i)
{
char *s;
if (!(flags & ASN1_PRINT_INDENT) || i == 0)
return NULL;
if (i > 128)
i = 128;
if ((s = malloc(i * 2 + 2)) == NULL)
return NULL;
s[0] = '\n';
s[i * 2 + 1] = '\0';
memset(s + 1, ' ', i * 2);
return s;
}
static struct rk_strpool *_asn1_print(const struct asn1_template *,
struct rk_strpool *,
int,
unsigned int,
const void *,
const heim_octet_string *);
/* See commentary in _asn1_decode_open_type() */
static struct rk_strpool *
_asn1_print_open_type(const struct asn1_template *t, /* object set template */
struct rk_strpool *r,
int flags,
unsigned int indent,
const void *data,
const char *opentype_name)
{
const struct asn1_template *tactual_type;
const struct asn1_template *tos = t->ptr;
const unsigned int *lenp = NULL; /* Pointer to array length field */
unsigned int len = 1; /* Array length */
size_t i;
const void * const *dp;
const void * const *val;
const int *elementp = DPOC(data, t->offset); /* Choice enum pointer */
char *indents = getindent(flags, indent);
char *s;
/* XXX We assume sizeof(enum) == sizeof(int) */
if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1) {
r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"_ERROR_DECODING_\"",
indents ? indents : "", opentype_name);
free(indents);
}
tactual_type = tos[3*(*elementp - 1) + 4].ptr;
r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"%s\"",
indents ? indents : "", opentype_name,
(const char *)tos[3*(*elementp - 1) + 2].ptr);
if (!r) {
free(indents);
return r;
}
if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
dp = DPOC(data, t->offset + sizeof(*elementp));
while (sizeof(void *) != sizeof(*elementp) &&
((uintptr_t)dp) % sizeof(void *) != 0)
dp = (void *)(((char *)dp) + sizeof(*elementp));
if (*dp) {
struct rk_strpool *r2 = NULL;
r2 = _asn1_print(tactual_type, r2, flags, indent + 1, *dp, NULL);
if (r2 == NULL) {
r = rk_strpoolprintf(r,
",%s\"_%s\":\"_ERROR_FORMATTING_\"",
indents ? indents : "", opentype_name);
free(indents);
return r;
}
s = rk_strpoolcollect(r2);
r = rk_strpoolprintf(r, ",%s\"_%s\":%s",
indents ? indents : "", opentype_name, s);
free(indents);
free(s);
}
return r;
}
lenp = DPOC(data, t->offset + sizeof(*elementp));
len = *lenp;
dp = DPOC(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
while (sizeof(void *) != sizeof(*elementp) &&
((uintptr_t)dp) % sizeof(void *) != 0)
dp = (void *)(((char *)dp) + sizeof(*elementp));
val = *dp;
r = rk_strpoolprintf(r, ",%s\"_%s\":[", indents ? indents : "",
opentype_name);
free(indents);
indents = getindent(flags, indent + 1);
if (indents)
r = rk_strpoolprintf(r, "%s", indents ? indents : "");
for (i = 0; r && i < len; i++) {
struct rk_strpool *r2 = NULL;
if (val[i]) {
r2 = _asn1_print(tactual_type, r2, flags, indent + 2, val[i], NULL);
if (r2 == NULL)
continue;
}
if (i)
r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
if (r)
r = rk_strpoolprintf(r, "%s", (s = rk_strpoolcollect(r2)));
free(s);
}
return rk_strpoolprintf(r, "]");
}
static struct rk_strpool *
_asn1_print(const struct asn1_template *t,
struct rk_strpool *r,
int flags,
unsigned int indent,
const void *data,
const heim_octet_string *saved)
{
const struct asn1_template *tbase = t;
const struct asn1_template *tnames;
size_t nelements = A1_HEADER_LEN(t);
size_t elements = nelements;
size_t nnames = 0;
char *indents = getindent(flags, indent);
for (t += nelements; t > tbase && (t->tt & A1_OP_MASK) == A1_OP_NAME; t--)
nnames++;
tnames = tbase + nelements - nnames + 1;
if (nnames)
r = rk_strpoolprintf(r, "%s{\"_type\":\"%s\"",
indents ? indents : "",
(const char *)(tnames++)->ptr);
if (saved && r) {
char *s = der_print_octet_string(data, 0);
if (!s) {
rk_strpoolfree(r);
free(indents);
return NULL;
}
r = rk_strpoolprintf(r, ",%s\"_save\":\"%s\"",
indents ? indents : "", s);
free(s);
}
saved = NULL;
if (tbase->tt & A1_HF_PRESERVE)
saved = data;
t = tbase + 1;
while (elements && (t->tt & A1_OP_MASK) != A1_OP_NAME) {
switch (t->tt & A1_OP_MASK) {
case A1_OP_NAME:
continue;
case A1_OP_DEFVAL:
t++;
elements--;
continue;
case A1_OP_OPENTYPE_OBJSET: {
size_t opentype = (t->tt >> 10) & ((1<<10)-1);
r = _asn1_print_open_type(t, r, flags, indent + 1, data,
tbase[(nelements - nnames) + 2 + opentype].ptr);
t++;
elements--;
continue;
}
default: break;
}
if (nnames)
r = rk_strpoolprintf(r, ",%s\"%s\":",
indents ? indents : "",
(const char *)(tnames++)->ptr);
switch (t->tt & A1_OP_MASK) {
case A1_OP_OPENTYPE_OBJSET:
break;
case A1_OP_NAME: break;
case A1_OP_DEFVAL: break;
case A1_OP_TYPE:
case A1_OP_TYPE_EXTERN: {
const void *el = DPOC(data, t->offset);
if (t->tt & A1_FLAG_OPTIONAL) {
const void * const *pel = (const void *const *)el;
if (*pel == NULL) {
r = rk_strpoolprintf(r, "null");
break;
}
el = *pel;
}
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
} else {
const struct asn1_type_func *f = t->ptr;
char *s2 = NULL;
char *s = NULL;
s = (f->print)(el, 0);
if (s == NULL ||
rk_strasvis(&s2, s, VIS_TAB|VIS_NL|VIS_DQ, "") == -1) {
rk_strpoolfree(r);
free(indents);
free(s);
return NULL;
}
free(s);
r = rk_strpoolprintf(r, "\"%s\"", s2);
free(s2);
}
break;
}
case A1_OP_PARSE: {
unsigned int type = A1_PARSE_TYPE(t->tt);
const void *el = DPOC(data, t->offset);
char *s = NULL;
if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
ABORT_ON_ERROR();
break;
}
s = (asn1_template_prim[type].print)(el, flags);
switch (type) {
case A1T_OID:
case A1T_BOOLEAN:
case A1T_INTEGER:
case A1T_INTEGER64:
case A1T_UNSIGNED:
case A1T_UNSIGNED64:
if (s)
r = rk_strpoolprintf(r, "%s", s);
break;
default: {
char *s2 = NULL;
if (s)
(void) rk_strasvis(&s2, s, VIS_TAB|VIS_NL|VIS_DQ, "");
free(s);
s = s2;
if (s)
r = rk_strpoolprintf(r, "\"%s\"", s);
}
}
if (!s) {
rk_strpoolfree(r);
free(indents);
return NULL;
}
free(s);
break;
}
case A1_OP_TAG: {
const void *el = DPOC(data, t->offset);
if (t->tt & A1_FLAG_OPTIONAL) {
const void * const *pel = (const void * const *)el;
if (*pel == NULL) {
r = rk_strpoolprintf(r, "null");
break;
}
el = *pel;
}
r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
break;
}
case A1_OP_SETOF:
case A1_OP_SEQOF: {
const struct template_of *el = DPOC(data, t->offset);
size_t ellen = _asn1_sizeofType(t->ptr);
const unsigned char *element = el->val;
unsigned int i;
r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
for (i = 0; r && i < el->len; i++) {
if (i)
r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
r = _asn1_print(t->ptr, r, flags, indent + 1, element, saved);
element += ellen;
}
if (r)
r = rk_strpoolprintf(r, "]");
break;
}
case A1_OP_BMEMBER: {
const struct asn1_template *bmember = t->ptr;
size_t size = bmember->offset;
size_t belements = A1_HEADER_LEN(bmember);
int first = 1;
bmember += belements;
r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
while (r && belements) {
if (!first)
r = rk_strpoolprintf(r, ",");
if (r && _asn1_bmember_isset_bit(data, bmember->offset, size))
r = rk_strpoolprintf(r, "%s\"%s\"", indents ? indents : "",
(const char *)bmember->ptr);
belements--; bmember--;
}
if (r)
r = rk_strpoolprintf(r, "]");
break;
}
case A1_OP_CHOICE: {
const struct asn1_template *choice = t->ptr;
const unsigned int *element = DPOC(data, choice->offset);
unsigned int nchoices = ((uintptr_t)choice->ptr) >> 1;
if (*element > A1_HEADER_LEN(choice)) {
r = rk_strpoolprintf(r, "null");
} else if (*element == 0) {
r = rk_strpoolprintf(r, "null");
} else {
choice += *element;
r = rk_strpoolprintf(r, "%s{\"_choice\":\"%s\",%s\"value\":",
indents ? indents : "",
(const char *)choice[nchoices].ptr,
indents ? indents : "");
if (r)
r = _asn1_print(choice->ptr, r, flags, indent + 1,
DPOC(data, choice->offset), NULL);
if (r)
r = rk_strpoolprintf(r, "}");
}
break;
}
default:
ABORT_ON_ERROR();
break;
}
t++;
elements--;
}
free(indents);
if (nnames && r)
return rk_strpoolprintf(r, "}");
return r;
}
char *
_asn1_print_top(const struct asn1_template *t,
int flags,
const void *data)
{
struct rk_strpool *r = _asn1_print(t, NULL, flags, 0, data, NULL);
if (r == NULL)
return NULL;
return rk_strpoolcollect(r);
}
/* See commentary in _asn1_decode_open_type() */
static int
_asn1_copy_open_type(const struct asn1_template *t, /* object set template */
@@ -2299,7 +2668,7 @@ _asn1_copy_open_type(const struct asn1_template *t, /* object set template */
memset(etop, 0, sizeof(int) + sizeof(void *));
return 0; /* Unknown choice -> not copied */
}
tactual_type = &tos[2*(*efromp - 1) + 2];
tactual_type = &tos[3*(*efromp - 1) + 4];
if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
dfromp = DPO(from, t->offset + sizeof(*efromp));