tags:

views:

252

answers:

2

I am working with the openSSL library's X509 certificate class, and I need to query the "key usage" extension.

After abandoning openSSL's vapourware "documentation", some shot-in-the-dark web searching eventually revealed that I needed to call

X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx)

and searching through the objects.h header revealed the proper NID.

Problem is, this call returns a pointer to void, which apparently can point to a variety of structs depending upon what extension one has asked for.

Since none of these appear to be documented, one is left without a way to figure out how to parse what the function returns.

Can anyone point me to a document that actually talks about this, instead of just listing things I can find out for myself (the function profile, which file it comes from, etc)?

+1  A: 

The second parameter (nid) determines the returned type.

Looking at this code:

http://opengrok.creo.hu/dragonfly/xref/src/crypto/openssl-0.9/crypto/x509v3/v3_purp.c#X509_check_purpose

It appears that for the key usage NID, it returns a ASN1_BIT_STRING. (line 361).

Joe
A: 

The easiest solutions to read the key usage seems to be

X509* x509_cert = ...
// without X509_check_ca x509_cert->ex_kusage always returns 0 (no idea why)
int ca = X509_check_ca(x509_cert);
unsigned long usage = x509_cert->ex_kusage;

The resulting values are defined in opensc/pkcs15-init.h

SC_PKCS15INIT_X509_DIGITAL_SIGNATURE     0x0080UL
SC_PKCS15INIT_X509_NON_REPUDIATION       0x0040UL
SC_PKCS15INIT_X509_KEY_ENCIPHERMENT      0x0020UL
SC_PKCS15INIT_X509_DATA_ENCIPHERMENT     0x0010UL
SC_PKCS15INIT_X509_KEY_AGREEMENT         0x0008UL
SC_PKCS15INIT_X509_KEY_CERT_SIGN         0x0004UL
SC_PKCS15INIT_X509_CRL_SIGN              0x0002UL

I came to that soultion by finding the following code of an openssl source file

/* Handle key usage */
if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
    if(usage->length > 0) {
        x->ex_kusage = usage->data[0];
        if(usage->length > 1) 
        x->ex_kusage |= usage->data[1] << 8;
    } else x->ex_kusage = 0;
    x->ex_flags |= EXFLAG_KUSAGE;
    ASN1_BIT_STRING_free(usage);
}
kuester2000