X509_EXTENSION Handling -- SSLeay 0.9.0b -- January 1999

NAME

X509_EXTENSION_dup, X509v3_get_ext, X509v3_delete_ext, X509v3_add_extension,
X509_EXTENSION_create_by_NID, X509_EXTENSION_create_by_OBJ, X509_EXTENSION_set_object,
X509_EXTENSION_set_critical, X509_EXTENSION_set_data, X509_EXTENSION_get_object,
X509_EXTENSION_get_data, X509_EXTENSION_get_critical, X509v3_data_type_by_OBJ,
X509v3_data_type_by_NID, X509v3_pack_type_by_OBJ, X509v3_pack_type_by_NID,
X509v3_pack_string, X509v3_unpack_string, X509v3_add_netscape_extensions -- X509_EXTENSION Handling

SYNOPSIS

#include "x509.h"

X509_EXTENSION *X509v3_get_ext(x, loc)
STACK *x;
int loc;

X509_EXTENSION *X509v3_delete_ext(x, loc)
STACK *x;
int loc;

int X509v3_add_extension(x)
X509_EXTENSION_METHOD *x;

X509_EXTENSION *X509_EXTENSION_create_by_NID(ex, nid, crit, data)
X509_EXTENSION **ex;
int nid;
int crit;
ASN1_OCTET_STRING *data;

X509_EXTENSION *X509_EXTENSION_create_by_OBJ(ex, obj, crit, data)
X509_EXTENSION **ex;
ASN1_OBJECT *obj;
int crit;
ASN1_OCTET_STRING *data;

int X509_EXTENSION_set_object(ex, obj)
X509_EXTENSION *ex;
ASN1_OBJECT *obj;

int X509_EXTENSION_set_critical(ex, crit)
X509_EXTENSION *ex;
int crit;

int X509_EXTENSION_set_data(ex, data)
X509_EXTENSION *ex;
ASN1_OCTET_STRING *data;

ASN1_OBJECT *X509_EXTENSION_get_object(ex)
X509_EXTENSION *ex;

ASN1_OCTET_STRING *X509_EXTENSION_get_data(ne)
X509_EXTENSION *ne;

int X509_EXTENSION_get_critical(ex)
X509_EXTENSION *ex;

int X509v3_data_type_by_OBJ(obj)
ASN1_OBJECT *obj;

int X509v3_data_type_by_NID(nid)
int nid;

int X509v3_pack_type_by_OBJ(obj)
ASN1_OBJECT *obj;

int X509v3_pack_type_by_NID(nid)
int nid;

ASN1_OCTET_STRING *X509v3_pack_string(ex, type, bytes, len)
ASN1_OCTET_STRING **ex;
int type;
unsigned char *bytes;
int len;

ASN1_STRING *X509v3_unpack_string(ex, type, os)
ASN1_STRING **ex;
int type;
ASN1_OCTET_STRING *os;

int X509v3_add_netscape_extensions();

DESCRIPTION

If you haven't read through the ASN.1 documentation, you probably had better do so; this library relies heavily on that code.

Here's the ASN.1 for the Extension subfield of the certificate:

Extension  ::=  SEQUENCE  {
     extnID      OBJECT IDENTIFIER,
     critical    BOOLEAN DEFAULT FALSE,
     extnValue   OCTET STRING  }

Now let's look at the EXTENSION subfield as the library defines it:

typedef struct X509_extension_st
        {
        ASN1_OBJECT *object;
        short critical;
        short netscape_hack;
        ASN1_OCTET_STRING *value;
        long argl;                      /* used when decoding */
        char *argp;                     /* used when decoding */
        void (*ex_free)();              /* clear argp stuff */
        } X509_EXTENSION;

The following structure is also used as support for extensions:

typedef struct x509_extension_method_st
{
  int nid;
  int data_type;
  int pack_type;
  void (*ex_clear)();
  int (*ex_get_bool)();
  int (*ex_set_bool)();
  int (*ex_get_str)();
  int (*ex_set_str)();
  char *(*ex_get_struct)();
  int (*ex_set_struct)();
  int (*a2i)();
  int (*i2a)();
} X509_EXTENSION_METHOD;

The only such method supported by the library at present is

static X509_EXTENSION_METHOD netscape_x509_ext[NETSCAPE_X509_EXT_NUM]={ {NID_netscape_ca_policy_url, V_ASN1_IA5STRING,X509_EXT_PACK_STRING}, {NID_netscape_ssl_server_name, V_ASN1_IA5STRING,X509_EXT_PACK_STRING}, {NID_netscape_revocation_url, V_ASN1_IA5STRING,X509_EXT_PACK_STRING}, {NID_netscape_base_url,V_ASN1_IA5STRING,X509_EXT_PACK_STRING}, {NID_netscape_cert_type,V_ASN1_BIT_STRING,X509_EXT_PACK_STRING}, {NID_netscape_ca_revocation_url,V_ASN1_IA5STRING,X509_EXT_PACK_STRING}, {NID_netscape_renewal_url,V_ASN1_IA5STRING,X509_EXT_PACK_STRING}, {NID_netscape_comment,V_ASN1_IA5STRING,X509_EXT_PACK_STRING}, };

Notice that it only fills in the first 3 elements of the structure; the rest are empty :(

The generic routines for new, free, and i2d/d2i conversion for X509_EXTENSION are discussed in X.509 Certificate Substructures; the functions specific to X509_EXTENSION only are described here.

X509_EXTENSION_dup is actually a macro:

#define X509_EXTENSION_dup(ex) 
  (X509_EXTENSION *)ASN1_dup((int (*)())i2d_X509_EXTENSION,
  (char *(*)())d2i_X509_EXTENSION,(char *)ex)

It makes a copy of the X509_EXTENSION structure that ex points to and returns it, or NULL on error.

X509v3_get_ext returns a pointer to the locth element of the stack x, nicely cast as X509_EXTENSION.

It returns NULL on error or if there is no locth element.

X509v3_delete_ext deletes the locth element of the stack (of X509_EXTENSION), returning a pointer to the data removed form the stack in case you want to use it for anything. On error, NULL is returned, or if there is no locth element.

X509v3_add_extension adds the X509_EXTENSION_METHOD x to the static stack extensions where it can then be checked later by X509v3_data_type_by_NID, X509v3_data_type_by_OBJ, X509v3_pack_type_by_NID, or X509v3_pack_type_by_OBJ (see below for descriptions of these functions). If your code supports an extension you need to define an EXTENSION_METHOD to support it and add it to the stack explicitly, so that you can then use the pack and unpack routines to stuff extensions into your requests/certificates/crls and get them back out again.

X509_EXTENSION_set_object makes a copy of obj, frees the object subfield of ex if it is setand stuffs it with the new copy of obj instead. It returns 1 if successful or 0 on error.

X509_EXTENSION_set_critical sets the critical subfield of ex if crit is nonxero, or clears it if crit is zero.

It returns 1 if successful or 0 if ex is NULL.

X509_EXTENSION_set_data sets the value subfield of ex to the ASN1_OCTET_STRING pointed to by data. It returns 1 if successful or 0 on error.

X509_EXTENSION_get_object returns a pointer to the object subfield of ex, or NULL if ex is NULL.

X509_EXTENSION_get_critical returns the integer critical subfield of ex, or 0 if ex is NULL. The subfield is a short and the function returns an integer. Hmmm...

X509_EXTENSION_get_data returns a pointer to the value subfield of ex or NULL if ex is NULL.

X509_EXTENSION_create_by_OBJ either populates *ex with the arguments passed to it, or if ex or *ex is NULL, allocates a new X509_EXTENSION structure and stuffs that. If ex is not NULL but *ex is, *ex will be set to point to the newly allocated structure.

A pointer to the newly populated structure is returned, or NULL on error.

X509_EXTENSION_create_by_NID does exactly the same thing as X509_EXTENSION_create_by_OBJ except that you pass a nid instead of an obj and the function calls OBJ_nid2obj to get an object from nid.

These functions are called by X509_print, to figure out how to write an extension in human-readable form. More functionality should be added.

X509v3_data_type_by_NID searches through a static stack of X509_EXTENSION_METHOD extensions, looking for one with the same nid as nid. If it finds one, it returns its type; otherwise, it returns V_ASN1_UNDEF. (Its type is checked by looking at the type subfield.)

X509v3_data_type_by_OBJ does the same thing as X509v3_data_type_by_NID except that you pass an obj instead of a nid, and the function calls OBJ_obj2nid to get a nid from the object.

X509v3_pack_type_by_NID searches through a static stack of X509_EXTENSION_METHOD extensions, looking for one with the same nid as nid. If it finds one, it returns its pack type; otherwise, it returns V_ASN1_UNDEF. (Its pack type is checked by looking at the pack_type subfield.)

X509v3_pack_type_by_OBJ does the same thing as X509v3_pack_type_by_NID except that you pass an obj instead of a nid, and the function calls OBJ_obj2nid to get a nid from the object.

X509v3_pack_string takes len bytes in bytes and using the type given in type converts it into DER-encoded form; it then puts together an ASN1_OCTET_STRING by using this DER-encoded string as the data part.

If type is V_ASN1_BIT_STRING or V_ASN1_OCTET_STRING, then the type set in the DER-encoding is the same. If the type is V_ASN1_IA5STRING, V_ASN1_PRINTABLESTRING or V_ASN1_T61STRING, then the type set is V_ASN1_UNIVERSAL. The new object is returned in *ex, or if ex or *ex is NULL a new object is malloced. If ex is not NULL but *ex is, then *ex gets set to point to the newly allocated structure.

A pointer to the new structure is returned, or NULL on error (including the case where the string is some other type than those listed above).

X509v3_unpack_string disassembles the ASN1_OCTET_STRING os whose data part is presumed to be a DER-encoded string that when converted to internal form is an ASN1_STRING of some sort.

The new data is placed in *ex. A pointer to it is also returned, or NULL on error.

If the type subfield of os is not one of V_ASN1_BIT_STRING, V_ASN1_OCTET_STRING, V_ASN1_IA5STRING, V_ASN1_PRINTABLESTRING, or V_ASN1_T61STRING then an error is logged and NULL is returned.

X509v3_add_netscape_extensions adds the extensions defined in the X509_EXTENSION_METHOD netscape_x509_ext to the static stack extensions by calling X509v3_add_extension. It returns 1 on success and 0 on error.

This function is called by apps/ca to allow processing of Netscape certificate extensions.