Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing asn1 document with openssl C API

I'd like to parse certificate in asn1 format using openssl library. Unfortunately, some API commands lack relevant documentation so I've tried them on my own. I've seen many relations to this topic but no precise usage explanation.

for start I'll consider the following command that should return general asn1 object.

int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
                int *pclass, long omax);

From examples i've found over the web, it seems like the input parameters description is as follow:

pp - pointer to the beginning of the object (or the certificate), it's changeable since after applying the function, this value move to the next object.

plength - output that represent the length of the object.

ptag - output that represent object type (simple like INTEGER, or complex the SEQUENCE).

pclass - I've no idea what does it means.

omax - the length until certificate end.

perhaps some openssl experienced user may validate my summary above, and clerify what does pclass means.

thanks

like image 736
Zohar81 Avatar asked Oct 21 '25 11:10

Zohar81


1 Answers

Answer

The pclass parameter represents the Tag Class which the Tag Number of the object's type is in.


Explanation

First, some background on an ASN.1 object. I'm going to simplify a lot here for the sake of explanation. When an ASN.1 object is encoded using BER/DER encoding, it's generally in the following structure:

+-------------------+---------------+-----------------+
| Identifier octets | Length octets | Contents octets |
| (Type)            | (Length)      | (Value)         |
+-------------------+---------------+-----------------+

The Identifier Octets are 8 bits which specify the type of the value. The Identifier Octets are usually encoded like this:

     +-----+-----+-----+-----+-----+-----+-----+-----+
Bits |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
     +-----------+-----+-----------------------------+
     | Tag class | P/C |         Tag number          |
     +-----------+-----+-----------------------------+

The Tag Class could be one of 4 things - Universal, Application, Context-specific, or Private. The Universal class contains the types which are native to ASN.1 (like Integer and String). Unless you're dealing with custom types, you can expect the class to be Universal, specified by 00. This is what gets returned via the pclass parameter.

The Tag Number is the 5 bits which specify the type within that class. This gets returned via the ptag parameter. For example, an Integer within the Universal class has the tag number 00010.

So, for example, you could test you got an ASN.1 Integer from ASN1_get_object in the following way:

ASN1_get_object(&pp, &plength, &ptag, &pclass, omax);
if (pclass == V_ASN1_UNIVERSAL && ptag == V_ASN1_INTEGER)
{
    // this is the native ASN.1 Integer type
}

If you know you're dealing purely with universal types, you might decide that testing the pclass variable is a bit redundant.


Documentation

Some of your definitions of what the parameters do are a little off. Here's my attempt at documentation for the function. I should point out I've tried to figure this out on my own by looking at the code and the ASN.1 spec, so I'd welcome any edits if I've got anything wrong.

int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, int *pclass, long omax)

Summary: Decodes a BER/DER-encoded ASN.1 object into its type, length and starting position of its value.

Parameters:

**pp: A pointer to a pointer to the start of the BER/DER encoded object. When the function returns, this pointer is adjusted to point to the start of the ASN.1 value (the contents octets).

*plength: A pointer to a long. When the function returns, this contains the length of the ASN.1 value, specified as a number of octets. If the length was encoded in the indefinite form, plength will be 0.

*ptag: A pointer to an int. When the function returns, this contains the ASN.1 Tag Number, which defines the type of the value. Note this is only the Tag Number, and doesn't include the Tag Class or the Primitive/Constructed indicator.

*pclass: A pointer to an int. When the function returns, this contains the class of the ASN.1 Tag.

omax: The maximum length of the BER/DER encoded object. If the object is longer than this, an error occurs.

Returns: An integer. If the 8th bit is set (0x80) then an error occurred. If the 6th bit is set (0x20) then the type is a constructed type (i.e. the contents octets encode one or more data values). If the 1st bit is set (0x01) then the length of the value is indefinite, and the value will end with the 'end-of-contents octets'.

like image 61
Craig Brown Avatar answered Oct 23 '25 03:10

Craig Brown