hi,

i finally got this thing working. that is, i have added custom
extensions to certificates. i will try to explain, as well as i can, how
i did it.

thanks to everyone that has helped me.

---------

Adding custom extensions to certificates
========================================

Note: The code provided in this document does not compile without some
      really simple modifications.

First we need  to create a new extension  identifier (object identifier,
OID) that will  identify the extension. The OID  is expressed in OpenSSL
by the ASN1_OBJECT structure. In OpenSSL we create a new OID like this:

   /**
    * First field is the OID itself, which will be converted to DER
    * encoding. Next fields are the short and long description of
    * this OID.
    * Note that the descriptions will not be included as the
    * extension identifier, but the DER encoding of the OID.
    */
    int nid = OBJ_create("1.2.3.4", "TestOID",
                         "Long description TesT OID");
    ASN1_OBJECT* obj = OBJ_nid2obj(nid);

OpenSSL has an static array of all available OIDs. Once you create a new
OID, as we did in the lines avobe, a new OID is added to OpenSSL, so one
can have access to the decriptions.



Next step is  to create our custom X509 extension  identified by the OID
created earlier. The  basic fields of an X509 extension  are: the OID, a
boolean  saying  whether the  extension  is  critical  or not,  and  the
extension data.  When an  extension is  critical it can  not be  read by
applications who do not know anything about it. so in our case we should
turn it to non-critical. Here is how we create our extension:

    /* Create data to be included in the extension */
    ASN1_OCTET_STRING* data = ::ASN1_OCTET_STRING_new();
    ASN1_OCTET_STRING_set(data, "our data", -1);

    /**
     * This will create our new extension, identified by our OID (obj
     * parameter). And with the data created above (data
     * parameter). The 0 means that the extension is non-critical.
     */
    X509_EXTENSION* ext = X509_EXTENSION_create_by_OBJ(NULL, obj, 0,
                                                       data);

Once  we have  our  extension,  we will  have  to include  it  to a  CSR
(Certificate Signing  Request), so the  CA that creates  our certificate
will include  it to it. We will  comment how to add  new extension using
OpenSSL commands.

    /**
     * Create a stack of X509_EXTENSION to add to our request.
     */
    STACK_OF(X509_EXTENSION)* exts = sk_X509_EXTENSION_new_null();
    sk_X509_EXTENSION_push(exts, ext);

    /**
     * Add the extensions to our CSR. Here it is supposed that the
     * CSR has been created previously.
     */
    X509_REQ_add_extensions(req, exts);

We can make sure that the  extensions have been added to the request, by
listing them with the follwing code:

    /**
     * We need to create our custom OID in order for OpenSSL to found
     * the short and long descriptions.
     */
    int nid = OBJ_create("1.2.3.4", "TestOID",
                         "Long description TesT OID");
    ASN1_OBJECT* obj = OBJ_nid2obj(nid);

    /**
     * Here we get the list of available extensions and iterate
     * through them.
     */
    STACK_OF(X509_EXTENSION)*  exts = X509_REQ_get_extensions(req);
    int n = sk_X509_EXTENSION_num(exts);
    printf("Extensions: %d\n", n);
    for (int i = 0; i < n; ++i)
    {
      X509_EXTENSION* ext = sk_X509_EXTENSION_value(exts, i);
      nid = OBJ_obj2nid(ext->object);
      printf("short name: %-22s - long name: %s\n", OBJ_nid2sn(nid),
             OBJ_nid2ln(nid));
    }

As I have  said before, we need to  create our OID in order  to view the
descriptions of  the extension's OID.  That is because  the descriptions
are not included  as part of the  OID in the extension. The  rest of the
code is easy to understand.

Now that we  have verified that our own extension is  inside the CSR, it
is time for the CA to create and sign our certificate and to include the
extra extensions found in the CSR to it.

For this, we now must use the commands provided by OpenSSL. In this case
we  will use  the "ca"  command to  create the  certificate.  The "x509"
command can also be used to create certificates from CSR, but it will be
unable to add extra extensions, so we can not use it for our purpose.

As  i  have  said,  we  will  use  the  "ca"  command.  In  the  OpenSSL
configuration file, there  is a section to configure  CA parameters. One
of these  parameters is "copy_extensions". In  our case, we  need to set
this parameter  to "copy",  which means the  CA will copy  all extension
present in the CSR to the certificate being created.

    copy_extensions = copy

You can find more information on CA parameters in the next URL:

http://www.openssl.org/docs/apps/ca.html#CONFIGURATION_FILE_OPTIONS

Next step is to finally create the certificate. Is as easy as this:

     openssl ca -cert ca.pem -keyfile ca-prikey.pem -outdir .
     -out certificate.pem -extensions usr_cert -extfile openssl.cnf
     -infiles request.csr

In the command above we just  provide the certificate and private key of
a CA,  two extensions  parameters that identifies  the extensions  to be
added  to  the certificate  (not  our own  extensions),  and  as a  last
parameter  our  CSR. This  will  create  our  certificate with  our  own
extension inside it.

For more information of the use of OpenSSL commands check out:

http://www.openssl.org/docs/apps/openssl.html

We  can   finally  check   the  existence  of   our  extension   in  the
certificate.  This   will  be  done   similarly  to  checking   the  CSR
extensions. Here is the code:

    /**
     * We need to create our custom OID in order for OpenSSL to found
     * the short and long descriptions.
     */
    int nid = OBJ_create("1.2.3.4", "TestOID",
                         "Long description TesT OID");
    ASN1_OBJECT* obj = OBJ_nid2obj(nid);

    /**
     * Here we get the list of available extensions and iterate
     * through them. Note the we suppose that the X509 certificate is
     * already created.
     */
    int n = X509_get_ext_count(cert);
    printf("Extensions: %d\n", n);
    for (i = 0; i < n; ++i)
    {
        X509_EXTENSION* ext = X509_get_ext(cert, i);
        nid = OBJ_obj2nid(ext->object);
        printf("short name: %-22s - long name: %s\n", OBJ_nid2sn(nid),
               OBJ_nid2ln(nid));
    }

That's it. I hope this  information will help other people adding custom
extensions to certificates.


Aleix Conchillo Flaque

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to