ASN.1/DER
Module Functionality
Provides a decoder for Abstract Syntax Notation One (ASN.1) encoding. This module allows programs to decode keyfiles using Distinguished Encoding Rules (DER), a serialization of ASN.1 standardized for cryptography.
ASN.1 encoding uses a series of tag-length-data pairs. The value may sometimes encapsulate other similarly encoded objects. For example, take a look at the PKCS#8 format for an RSA public key as well as some corresponding hexdump output:
PublicKeyInfo ::= SEQUENCE {
algorithm ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
PublicKey BIT STRING
}
30 81 9f
30 0d
06 09 2a 86 48 86 f7 0d 01 01 01
05 00
03 81 8d 00 30 81 89 02 81 81 00 c0 3c a0 1c 0b 0e be b0 64 62 fc 2e 0e 8d 04 9d
c1 a7 c7 ce 88 8d 85 87 6a 41 93 45 25 23 25 38 74 ce 4f f1 46 f5 3b 94
19 b2 1d 6d fc a0 46 04 64 c6 b2 33 77 2f b9 89 33 6a ce 84 8a 5a ff 88
1f 03 38 31 1d e6 08 dd d0 ae 86 fd f5 d9 25 4f 82 1c 93 a4 cc 32 22 67
a2 16 68 b9 d6 ae e4 b2 ee 80 93 b1 4a 2b 80 27 27 fd 99 18 90 b6 e2 97
2a 14 51 02 ca 73 36 41 52 18 dc a8 e8 69 44 09 02 03 01 00 01
Note how in some of the tag-length-data groups there is a prefix byte of 0x81
(or similar) between the tag and the data length that seems to do nothing. It is actually a serialization of the size word. For a data size of more than 128 bytes a signed byte prefixes the size word indicating the length of the size word. If the size would require three (3) bytes, for example, then the byte 0x83
would prefix it instead.
Enumerations
-
enum cryptx_asn1_tags
Values:
-
enumerator ASN1_RESVD = 0
RESERVED.
-
enumerator ASN1_BOOLEAN
defines a BOOLEAN object
-
enumerator ASN1_INTEGER
defines an INTEGER object
-
enumerator ASN1_BITSTRING
defines a BIT STRING object
-
enumerator ASN1_OCTETSTRING
defines an OCTET STRING object
-
enumerator ASN1_NULL
defines a NULL object (0 size, no data)
-
enumerator ASN1_OBJECTID
defines an OBJECT IDENTIFIER
-
enumerator ASN1_OBJECTDESC
defines an OBJECT DESCRIPTION
-
enumerator ASN1_INSTANCE
defines an INSTANCE
-
enumerator ASN1_REAL
defines a REAL object
-
enumerator ASN1_ENUMERATED
-
enumerator ASN1_EMBEDDEDPDV
-
enumerator ASN1_UTF8STRING
-
enumerator ASN1_RELATIVEOID
-
enumerator ASN1_SEQUENCE = 16
defines a SEQUENCE
-
enumerator ASN1_SET
defines a SET
-
enumerator ASN1_NUMERICSTRING
-
enumerator ASN1_PRINTABLESTRING
-
enumerator ASN1_TELETEXSTRING
-
enumerator ASN1_VIDEOTEXSTRING
-
enumerator ASN1_IA5STRING
-
enumerator ASN1_UTCTIME
-
enumerator ASN1_GENERALIZEDTIME
-
enumerator ASN1_GRAPHICSTRING
-
enumerator ASN1_VISIBLESTRING
-
enumerator ASN1_GENERALSTRING
-
enumerator ASN1_UNIVERSALSTRING
-
enumerator ASN1_CHARSTRING
-
enumerator ASN1_BMPSTRING
-
enumerator ASN1_RESVD = 0
-
enum cryptx_asn1_classes
Values:
-
enumerator ASN1_UNIVERSAL
tags defined in the ASN.1 standard.
Most use cases on calc will be this.
-
enumerator ASN1_APPLICATION
tags unique to a particular application.
-
enumerator ASN1_CONTEXTSPEC
tags that need to be identified within a particular, well-definded context.
-
enumerator ASN1_PRIVATE
reserved for use by a specific entity for their applications.
-
enumerator ASN1_UNIVERSAL
Macros
The ASN.1 tag is an octet consisting of three (3) parts, (1) A 5-bit tag value which is one of the items in the cryptx_asn1_tags enum above, (2) A 2-bit class value which is one of the items in the cryptx_asn1_classes enum, and (3) a 1-bit form indicating if the item is constructed [encapsulates other encoded elements] or primitive [contains no encapsulated data].
-
cryptx_asn1_gettag(tag)
Returns the unmasked tag. See cryptx_asn1_tags above.
-
cryptx_asn1_getclass(tag)
Returns the 2-bit tag class flag. See cryptx_asn1_classes above.
-
cryptx_asn1_getform(tag)
Returns the 1-bit tag form (1 = constructed, 0 = primitive). See cryptx_asn1_forms above.
Response Codes
-
enum asn1_error_t
Defines error codes returned from calls to the ASN.1 API.
Values:
-
enumerator ASN1_OK
No errors occured.
-
enumerator ASN1_END_OF_FILE
End of ASN.1 data stream reached.
Technically not an error.
-
enumerator ASN1_INVALID_ARG
One or more arguments invalid.
-
enumerator ASN1_LEN_OVERFLOW
Length of an element overflowed arch size_t allowance.
Remainder of data stream unparsable.
-
enumerator ASN1_OK
Functions
-
asn1_error_t cryptx_asn1_decode(void *parse_begin, size_t parse_len, uint8_t index, struct cryptx_asn1_object *object)
Decodes the ASN.1 data at the given address.
Seeks to an element from the front of the data.
Note
Function does not recurse the ASN.1 tree structure automatically. It parses all elements at the tree level determined by parse_begin and parse_len. You may recurse manually by checking the value of cryptx_asn1_getform() on the last returned object->tag and then calling cryptx_asn1_decode() with object->data as parse_begin and object->len as parse_len.
Note
If you are using this function to decode a PKCS#8 structure for use with this library, use the PKCS#8 wrapper module instead.
- Parameters
parse_begin – Pointer to a block of ASN.1-encoded data to parse.
parse_len – Length of ASN.1-encoded block to parse.
index – Return index-th encoded element of current tree level.
object – Pointer to an asn1_object to populate.
- Returns
An asn1_error_t indicating the status of the operation. If index is past the end of the data, ASN1_END_OF_FILE is returned.
Here is a simple example of how to loop each element in an ASN.1 structure and return its metadata. Note how a return value of ASN1_END_OF_FILE is used as a limiter. Also notice how recursion is achieved.
void decode_level(uint8_t *data, size_t len){
cryptx_asn1_object obj;
uint8_t index = 0
asn1_error_t err = ASN1_OK;
do {
err = cryptx_asn1_decode(data, len, index++, &obj);
if(err == ASN1_OK){
printf("element -- tag:%u, len:%u, data:%p\n", obj.tag, obj.len, obj.data);
if(cryptx_asn1_getform(obj.tag)) // is a constructed object
decode_level(obj.data, obj.len);
}
else {
printf("error code: %u", err);
break;
}
} while(err != ASN1_END_OF_FILE);
}
int main(void){
// assume `asn1_data` is some imported data encoded with ASN.1
decode_level(asn1_data, sizeof(asn1_data));
}