X.509v3 ASN.1 to C datastructs

2019-05-18 00:19发布

I'm trying to create a X509 Request for a Proxy Certificate (ProxyCertInfo Extension RFC3820) in C (OpenSSL), but I cannot figure out how the datastructures of the ProxyCertInfo should be defined. The RFC defines the ASN.1 language as follows:

PKIXproxy88 { iso(1) identified-organization(3) dod(6)
   internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
   proxy-cert-extns(25) }

DEFINITIONS EXPLICIT TAGS ::=

BEGIN

-- EXPORTS ALL --

-- IMPORTS NONE --

-- PKIX specific OIDs

id-pkix OBJECT IDENTIFIER ::=
       { iso(1) identified-organization(3)
            dod(6) internet(1) security(5) mechanisms(5) pkix(7) }

-- private certificate extensions
id-pe   OBJECT IDENTIFIER ::= { id-pkix 1 }

-- Locally defined OIDs

-- The proxy certificate extension
id-pe-proxyCertInfo    OBJECT IDENTIFIER ::= { id-pe 14 }

-- Proxy certificate policy languages
id-ppl  OBJECT IDENTIFIER ::= { id-pkix 21 }

-- Proxy certificate policies languages defined in
id-ppl-anyLanguage     OBJECT IDENTIFIER ::= { id-ppl 0 }
id-ppl-inheritAll      OBJECT IDENTIFIER ::= { id-ppl 1 }
id-ppl-independent     OBJECT IDENTIFIER ::= { id-ppl 2 }

-- The ProxyCertInfo Extension
ProxyCertInfoExtension  ::= SEQUENCE {
     pCPathLenConstraint     ProxyCertPathLengthConstraint OPTIONAL,
     proxyPolicy             ProxyPolicy
}

ProxyCertPathLengthConstraint  ::= INTEGER
ProxyPolicy  ::= SEQUENCE {
     policyLanguage          OBJECT IDENTIFIER,
     policy                  OCTET STRING OPTIONAL
}

END

I have looked at the very limited documentation of OpenSSL and cannot find out how to parse this to C data structs. I've also read http://www.openssl.org/docs/apps/asn1parse.html# as it explains how to use the parser for the command line tool, but not how to include this in your own source code.

I have managed to include other extensions to the X509 request already, so I'm relatively sure my only problem is with the formatting of the data structures for this particular extension.

1条回答
劫难
2楼-- · 2019-05-18 01:09

I think your question is "How do I format data as a ProxyCertInfoExtension?" If this in incorrect please let me know.

If you want to know some theory, the best reference I have found is A Layman's Guide to a Subset of ASN.1, BER, and DER.

The code section in your question is a description of how the data for the ProxyCertInfoExtension is encoded. Think of the encoding description as a grammar that could be processed by a parser generator, much as yacc take a grammar as input and outputs C code. In fact at least one ASN.1 parser generator exists ASN1C

ASN.1 encodings may be of variable size. The data begins with an outtermost or top level ASN.1 encoding. Each ASN.1 encoding may contain one or more ASN.1 encoding inside itself. In this way ASN.1 is recursive.

An ASN.1 encoding is composed of a header, a length, optional content, and an optional end.

ASN.1 encoding { Header length [content] [end] }

The header is composed of a Class type, a Primitive/Constructed bit, and a Tag-Number. If the Tag-Number is larger than 63 then the Tag-Number will span multiple bytes. This means that the header may be one byte long or many bytes long depending on the value of the Tag-Number. The header is byte aligned meaning that is always some number of bytes long.

ASN.1 header { ClassType Primitive/Constructed Tag-number }

The length may also be one byte to many bytes long depending on the value of the length. Again the Length is byte aligned.

The Class type and the Tag-Number tell you what is encoded in the Content.

The outtermost encoding is usually a sequence or set, which are compound basic types. In your encoding, the outtermost encoding is the ProxyCertInfoExtension which is a sequence of an optional ProxyCertPathLengthConstraint and a ProxyPolicy. Your encoding looks like this:

ProxyCertInfoExtension { [ProxyCertPathLengthConstraint] ProxyPolicy }

Looking back at the encoding rules, ProxyCertPathLengthConstraint is just an integer, so your encoding is really:

ProxyCertInfoExtension { [Integer] ProxyPolicy }

The encoding rules define a ProxyPolicy as a sequence of a policyLanguage and an optional policy. So we can update the encoding representation to look like this:

ProxyCertInfoExtension { [Integer] { policyLanguage [policy] } }

The encoding rules specify policy as an Octet String (Just some number of bytes). So firther simplification produces:

ProxyCertInfoExtension { [Integer] { policyLanguage [Octet String] } }

Depending on the object identifier, the encoding is one of:

ProxyCertInfoExtension { [Integer] { id-ppl-anyLanguage [Octet String] } }
ProxyCertInfoExtension { [Integer] { id-ppl-inheritAll  [Octet String] } }
ProxyCertInfoExtension { [Integer] { id-ppl-independent [Octet String] } }

I'll try an untested example ProxyCertPathLengthConstraint=64 policyLanguage=id-ppl-anyLanguage policy="test" I'll work inside out starting with policy length is 04 this is a printable string so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x13 the header byte is 0x13 length=4, so length byte is 0x04 "test" in ascii is 0x74 0x65 0x73 0x74 the encoding for policy is 0x13 0x04 0x74 0x65 0x73 0x74

id-ppl-anyLanguage is an Object Identifier so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x06 the header byte is 0x06 the value for id-ppl-anyLanguage is "1.3.6.1.5.5.7.21.0" length=18, so length byte is 0x12 "1.3.6.1.5.5.7.21.0" = 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 the encoding for policyLanguage is 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10

proxyPolicy is a sequence so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x10 the header byte is 0x10 the length= lengthof(policyLanguage) + lengthof(policy) = (lengthof(policyLanguage headers) + lengthof (policyLanguage content)) + (lengthof(policyheaders) + lengthof (policy content)) = (2 + 4) + (2 + 18) = 6 + 20 = 26 length=26, so length byte is 0x1A the content is policyLanguage followed by policy = 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74 the encoding for proxyPolicy is 0x10 0x1A 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74

ProxyCertPathLengthConstraint is a integer so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x02 the header byte is 0x02 the length=0x01 the content=0x40 the encoding is 0x02 0x01 0x40

ProxyCertInfoExtension is a SEQUENCE so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x10 the header byte is 0x10 the length = lengthof(pCPathLenConstraint) + lengthof(proxyPolicy) = lengthof(pCPathLenConstraint headers) + lengthof (pCPathLenConstraint content)) + (lengthof(proxyPolicy headers) + lengthof(proxyPolicy content)) = (2 + 1) + (2 + 26) = 3 + 28 = 31 = 0x1F the content= pCPathLenConstraint followed by proxyPolicy = 0x02 0x01 0x40 0x10 0x1A 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74 the encoding is 0x10 0x1F 0x02 0x01 0x40 0x10 0x1A 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74

查看更多
登录 后发表回答