11

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?

Roger Dahl
  • 15,132
  • 8
  • 62
  • 82
  • 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 Sep 07 '11 at 17:30
  • 1
    @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 Sep 08 '11 at 03:01
  • 1
    @Francois: I found out how to use the function and posted an answer based on that. Thanks again. – Roger Dahl Sep 08 '11 at 04:52

1 Answers1

8

@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);
Roger Dahl
  • 15,132
  • 8
  • 62
  • 82
  • 1
    I was trying to do the exact same thing, but when applying your solution, I get the same string as before the call to ASN1_get_object function. Are you sure this function der decodes? – Maggie Apr 07 '12 at 16:53
  • 1
    @Maggie: For the ASN.1 type that I was handling, `OCTET STRING`, it works. But it could be that it works because the only thing DER encoding does to an `OCTET STRING` is to wrap it up with a header. The bytes themselves stay the same. ASN1_get_object() does remove the header, but maybe that is *all* it does? – Roger Dahl Apr 08 '12 at 02:10
  • 1
    as I said, I am doing the EXACT same thing, ie. trying to get the human-readable value of the der-encoded certificate extension using openssl. the solution you provided does not work. – Maggie Apr 09 '12 at 08:30
  • 1
    @Maggie: Is your certificate extension also an `OCTET STRING`? – Roger Dahl Apr 09 '12 at 12:24
  • 2
    Yes, the ASN.1 simple types are `BOOLEAN`, `INTEGER`, `BIT STRING`, `OCTET STRING`, `NULL`, `OBJECT IDENTIFIER`, `REAL`, `ENUMERATED` and `CHARACTER STRING`. – Roger Dahl Apr 09 '12 at 17:27
  • 1
    ok, how do I get data from X509 extension, except calling: ASN1_OCTET_STRING* octet_str = X509_EXTENSION_get_data(extension); – Maggie Apr 09 '12 at 17:40
  • 2
    It appears that you are seeking a general solution on how to extract the information in an x509v3 extension. As the title of this question states, it is only about the special case of decoding a single `OCTET STRING`. Beyond that, I can only point you to the original suggestion of @Francois, which is to use an external ASN.1 parser, such as SNACC or libtasn1 and to look at the OpenSSL source code (around crypto/asn1/asn1_par.c:135). – Roger Dahl Apr 09 '12 at 18:01
  • 1
    @RogerDahl Just so you're more fully informed, this appears to be runoff from a question posted [here](http://stackoverflow.com/questions/10012981/openssl-get-certificate-extensions). There's an open bounty, if you're interested in providing a more complete answer. :) – MrGomez Apr 09 '12 at 19:14
  • 4
    @MrGomez: Thanks for the link. Wild horses could not drag me back to the OpenSSL API :) – Roger Dahl Apr 09 '12 at 22:26