Current location - Quotes Website - Signature design - Application of ASN 1 in OpenSSL
Application of ASN 1 in OpenSSL
Asn. 1-abstract grammatical symbol dot one, abstract symbol1,which will be abbreviated as ASN 1 in most writing situations. It describes the data format used to represent, encode, transmit and decode data. It provides a set of formal formats to describe the structure of objects, which has nothing to do with the language implementation and the specific reference of these data, nor with what kind of application it is.

There are many implementation versions of ASN 1, and OpenSSL mainly adopts DER format.

This article assumes that you have installed OpenSSL and have a copy of the source code of 1. 1. 1

The header files related to ASN 1 are asn 1.h and asn 1t.h, and the source files are in the crypto/asn 1 directory.

This structure is responsible for managing the memory organization of most data types in ANS 1. The fields have the following meanings:

The data length of length management.

Type-managed data types.

Data-data pointer.

Flags-Flags associated with a specific data type.

Data types managed:

Value of primary data type:

Other types of definitions:

In the implementation of OpenSSL, each data type has an entry structure, which is responsible for defining the encoding and decoding rules of the data type.

Related fields have the following meanings:

Itype- defines the type of the project itself, and the value is:

Utype- defines the managed data type, the value of which was explained earlier, such as V_ASN 1_INTEGER.

Template-data processing method template array pointer.

T count- the number of template arrays.

Funcs- callback method pointer.

Size-Responsible for the size of the data structure.

Sname-the name that points to the data structure.

As mentioned earlier, for each data type, OpenSSL needs a corresponding entry structure. The following macro declares the project structure for each data type, and also declares the corresponding mnemonic function. As follows:

Take declare _ ASN1_ functions (ASN1_ integer), and expand the macro definition as follows:

There are also several macros that are responsible for implementing the corresponding mnemonic functions for data types. As follows:

Taking implementation _ ASN1_ item (ASN1_ integer) as an example, its expansion form is:

It can be seen that the mnemonic function realized in the extended form is actually an encapsulated call to several internal functions of ASN 1, which provides the conversion between the upper data type and the internal type, where ASN 1_VALUE is the link between the upper and lower types and is a universal pointer:

typedef struct ASN 1 _ VALUE _ ST ASN 1 _ VALUE;

In asn 1.h, mnemonic functions are declared for basic data types:

But I haven't found the macro implementation of the basic data type mnemonic function yet.

The ASN 1 encoding process of OpenSSL depends on the ASN 1_ITEM object. For basic types, OpenSSL itself has been declared and initialized, so it can be used directly in related functions. But for custom structures, developers need to define ASN 1_ITEM objects and rules. There are some macros that can help. Excerpts are as follows:

In the structure of ASN 1_ITEM, the structure of ASN 1_TEMPLATE is defined as follows:

Main field meaning:

Offset- The offset of the field in the parent structure.

Field Name-The field name.

Point to the ASN 1_ITEM object of the structure type corresponding to the field.

For example, define the following custom structures:

Expand the macro to:

ASN 1 _ VALUE * ASN 1 _ ITEM _ new(const ASN 1 _ ITEM * it);

void ASN 1 _ ITEM _ free(ASN 1 _ VALUE * val,const ASN 1 _ ITEM * it);

Create and publish corresponding data types according to project objects.

ASN 1 _ VALUE * ASN 1 _ ITEM _ d2i(ASN 1 _ VALUE * * val,const unsigned char **in,long len,const ASN 1 _ ITEM * it);

According to the ITEM object, the DER code is converted into a binary structure.

A valid pointer was successfully returned and NULL was successfully returned.

If val is NULL, memory will be allocated internally, but it must be released by external users.

Its internal realization is:

You can see that the compatibility processing of passing in NULL for val is done internally.

int ASN 1 _ ITEM _ i2d(ASN 1 _ VALUE * val,unsigned char **out,const ASN 1 _ ITEM * it);

Convert the binary structure into DER encoding according to the ITEM object.

DER code length returned successfully, and returned negative number if failed.

If *out is NULL, memory will be allocated internally, but memory must be released by external users. If **out is NULL, only the length is returned to test the length of the scene.

Its internal realization is:

You can see that the internal compatibility processing is to pass in NULL to out and *out. When out passes in NULL, the buffer cannot be received, and only the length can be returned.

void * ASN 1 _ ITEM _ d2i _ BIO(const ASN 1 _ ITEM * it,BIO *in,void * x);

According to the ITEM object, the DER code is converted into a binary structure, and the entered DER code comes from the BIO object.

A valid pointer was successfully returned and NULL was successfully returned.

Actually, this function is an encapsulated call to ASN 1_item_d2i ().

Its internal realization is:

void * ASN 1 _ ITEM _ d2i _ FP(const ASN 1 _ ITEM * it,FILE *in,void * x);

The file version of ASN 1_item_d2i_bio ().

The functions ASN 1_item_d2i_bio () and ASN 1_item_d2i_fp () are not suitable for defining the type of output parameter X. The following functions ASN 1_d2i_bio () and ASN 1_d2i_bio.

int ASN 1 _ ITEM _ i2d _ BIO(const ASN 1 _ ITEM * it,BIO *out,void * x);

According to the ITEM object, the binary structure is converted into DER code and output to the BIO object.

DER code length returned successfully, and returned negative number if failed.

If *out is NULL, memory will be allocated internally, but memory must be released by external users. Actually, this function is an encapsulated call to ASN 1_item_i2d ().

Its internal realization is:

int ASN 1 _ ITEM _ i2d _ FP(const ASN 1 _ ITEM * it,FILE *out,void * x);

The file version of ASN 1_item_i2d_bio ().

In fact, the above functions are rarely used directly in programs, because they directly need ASN 1_ITEM as a parameter, but are replaced by variables declared by the macro DECLARE_ASN 1_FUNCTIONS or the functions described below.

void * ASN 1 _ d2i _ BIO(void *(* xnew)(void),d2i_of_void *d2i,BIO *in,void * * x);

Read the data encoded by DER from the BIO object and convert it into the corresponding binary structure. The specific conversion depends on the d2i function pointer.

A valid pointer was successfully returned, or NULL if it was changed.

Its internal realization is:

void * ASN 1 _ d2i _ FP(void *(* xnew)(void),d2i_of_void *d2i,FILE *in,void * * x);

The file version of ASN 1_d2i_bio ().

int ASN 1 _ i2d _ BIO(i2d _ of _ void * i2d,BIO *out,unsigned char * x);

Convert the binary structure into DER code and output it to BIO. The specific conversion depends on the i2d function pointer.

1 returned successfully, and 0 failed.

Its internal realization is:

int ASN 1 _ i2d _ FP(i2d _ of _ void * i2d,FILE *out,void * x);

The file version of ASN 1_i2d_bio ().

The signatures of d2i_of_void and i2d_of_void functions above are:

Usually a conversion mnemonic function of data type.

int ASN 1 _ INTEGER _ set(ASN 1 _ INTEGER * a,long v);

Set the value of v to a, and return 1 on success or 0 on failure.

long ASN 1 _ INTEGER _ get(const ASN 1 _ INTEGER * a);

Gets the integer value stored in the. Failed to return-1.

int ASN 1 _ ENUMERATED _ set(ASN 1 _ ENUMERATED * a,long v);

Set the value of v to a, and return 1 on success or 0 on failure.

long ASN 1 _ ENUMERATED _ get(const ASN 1 _ ENUMERATED * a);

Gets the enumeration values stored in the. Failed to return-1.

int ASN 1 _ STRING _ set(ASN 1 _ STRING * str,const void *data,int len);

Set the string values pointed by data and len to str. 1 returned successfully, and 0 failed.

Unsigned char * ASN1_ string _ data (ASN1_ string * x);

Get the first pointer of the string X, return a valid pointer successfully, and return NULL if it fails.

int ASN 1 _ STRING _ length(const ASN 1 _ STRING * x);

Gets the string length of x.

int i2a _ ASN 1 _ INTEGER(BIO * BP,const ASN 1 _ INTEGER * a);

Convert ASN 1_INTEGER into ASC code and output it to bp. 1 returned successfully, and 0 failed.

int a2i _ ASN 1 _ INTEGER(BIO * BP,ASN 1_INTEGER *bs,char *buf,int size);

Convert the ASC code in bp into ASN 1_INTEGER, and buf stores the ASC code of BIO. 1 returned successfully, and 0 failed.

int i2a _ ASN 1 _ ENUMERATED(BIO * BP,const ASN 1 _ ENUMERATED * a);

Convert ASN 1_ENUMERATED into ASC code and output it to bp. 1 returned successfully, and 0 failed.

int a2i _ ASN 1 _ ENUMERATED(BIO * BP,ASN 1_ENUMERATED *bs,char *buf,int size);

Convert the ASC code in bp into ASN 1_ENUMERATED, and buf stores the ASC code of BIO. 1 returned successfully, and 0 failed.

Inti2a _ ASN1_ string (bio * BP, const ASN 1_STRING *a, int type);

Convert the string in A into ASC code and output it to bp. type doesn't work. Returns the converted ASC string length.

int a2i _ ASN 1 _ STRING(BIO * BP,ASN 1_STRING *bs,char *buf,int size);

Convert the ASC code in bp into ASN 1_STRING, and buf stores the ASC code of BIO. 1 returned successfully, and 0 failed.

ASN 1 _ OBJECT * ASN 1 _ OBJECT _ new(void);

Assign OID objects.

void ASN 1 _ OBJECT _ free(ASN 1 _ OBJECT * a);

Releases OID objects.

The encoding rule of OID is: the first octet adopts the formula: first_arc* 40+second_arc. If a number is greater than 127, it is represented by a plurality of 8 bits. The highest bit 1 means that there is an octet in the following, and 0 means that there is no octet in the following. Successfully returned the number of bytes encoded by OID.

int a2d _ ASN 1 _ OBJECT(unsigned char * out,int olen,const char *buf,int num);

Calculates the DER encoding of the OID specified by the ASC string. Returns the number of bytes encoded. Therefore, it is necessary to know the length of the code in advance to allocate memory. You can set out to NULL and olen to 0 to get the length of encoded bytes, and then allocate memory according to this length.

ASN 1 _ OBJECT * d2i _ ASN 1 _ OBJECT(ASN 1 _ OBJECT * * a,const unsigned char **pp,long length);

Convert DER encoding to OID object. A valid pointer was successfully returned.

Inti2d _ ASN1_ object (constasn1_ object * a, unsigned char * * PP);

Convert OID objects to DER encoding. Returns the length of DER encoding.

int i2a _ ASN 1 _ OBJECT(BIO * BP,const ASN 1 _ OBJECT * a);

Convert DER code into ASC string and output the result to bp. Returns the length of ASC string.

The following examples test the usage of many functions. Please post a comment and test it yourself.