OpenSSL x509 Certificate: Add Extension with X509_

2019-07-08 19:39发布

问题:

Context:

I'm generating an x509 Certificate using APIs in OpenSSL. I first create the X509 structure like this:

X509 *x509 = X509_new();   // Assume no errors

What I'm trying to do:

Now I want to add an extension to this Certificate. Specifically, I want to set the "Extended Key Usage" extension to the value serverAuth,clientAuth. To do this, I am attempting to use the OpenSSL function x509_add1_ext_i2d(), which has the following signature:

X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags)

I'm calling that function passing a C-String for value, which I assume is not correct. Here's the call I'm making:

X509_add1_ext_i2d(x509, NID_ext_key_usage, "serverAuth,clientAuth", 0, 0)

What's Happening:

I'm getting an EXC_BAD_ACCESS (code=EXC_i386_GPFLT) exception when that line of code runs. I'm assuming that's because the value I pass in has to be some sort of special thing (an octet string? Some sort of other OpenSSL value?)


What I Need:

What do I need to pass for the value parameter in order to correctly set that extension to the string value serverAuth,clientAuth? Or, alternately, why am I getting the listed exception? Note: If I remove this line and attempt to generate a certificate without extensions (with other properties such as Name, expiration date, etc. that I have excluded here for brevity) it works just fine.

I have spent an entire day pouring over OpenSSL's (ridiculously poor) documentation and Googling. Everything I can find discusses how to add extensions to certificates from the command line rather than in code. I cannot track down what the hell this function expects to see in the value parameter.

回答1:

After some more rooting around in OpenSSL's source, I stumbled across a function in the makecert.c example that also does this. I've cleaned it up slightly, and here it is. You pass in the NID of the extension you want to set and a simple string value for it. Very handy:

BOOL addExtension(X509 *cert, int nid, char *value)
{
    X509_EXTENSION *ex = NULL;
    X509V3_CTX ctx;

    // This sets the 'context' of the extensions. No configuration database
    X509V3_set_ctx_nodb(&ctx);

    // Issuer and subject certs: both the target since it is self signed, no request and no CRL
    X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
    ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
    if (!ex) {
        return NO;
    }

    int result = X509_add_ext(cert, ex, -1);

    X509_EXTENSION_free(ex);

    return (result == 0) ? YES : NO;
}