10
votes

Using the OpenSSL API, I have extracted a custom extension from a X.509v3 certificate with:

X509_EXTENSION* ex = X509_get_ext(x509, 4);

The X509_EXTENSION object contains a value (ex->value) that is an ASN.1 OCTET STRING. The OCTET STRING contains a DER encoded UTF-8 string. I'm trying to decode the OCTET STRING to get the plain UTF-8 string.

I have tried a few things, such as:

ASN1_STRING_to_UTF8(&buf, ex->value);

and

M_ASN1_OCTET_STRING_print(bio, ex->value);
int len = BIO_read(bio, buf, buf_size);
buf[len] = '\0';

These both give me the DER encoded string. How do I get the plain UTF-8 string?

1
I used 'asn1_get_object' to do this a while ago, following the example in openssl code (around crypto/asn1/asn1_par.c:135). It's so painful to decode a big structure this way that I recommend to use an alternate asn1 parser such as SNACC or libtasn1.Francois
@Francois: Thank you for the tip. Since I'm not trying to decode a big structure, just a single string, ASN1_get_object() might be adequate. However, I made an attempt at using it, based on how it's used in asn1_par.c, but couldn't get it working. Would you be able to provide an example?Roger Dahl
@Francois: I found out how to use the function and posted an answer based on that. Thanks again.Roger Dahl

1 Answers

7
votes

@Francois pointed me to the ASN1_get_object() function. That function is appropriate for this scenario where the certificate extension contains only a single value.

ASN1_get_object() takes a pointer to a pointer to a C buffer that contains a DER encoded object. It returns the data itself (by adjusting the pointer), the length of the data, the ASN.1 tag value and the ASN.1 object class.

ASN1_OCTET_STRING* octet_str = X509_EXTENSION_get_data(extension);
const unsigned char* octet_str_data = octet_str->data;
long xlen;
int tag, xclass;
int ret = ASN1_get_object(&octet_str_data, &xlen, &tag, &xclass, octet_str->length);
printf("value: %s\n", octet_str_data);