The project I have to extend is using mbedTLS and I have to extract the subject key identifier extension from the certificate. I have not found a workable solution so far. mbedTLS does not offer a direct function for this.
I have found mbedtls_x509_get_ext
but this seems to be an internal function and very low level. I also do not have the offsets. I have also found the v3_ext
storing maybe all extension as an mbedtls_x509_buf
. I guess this could be parsed as ASN.1. a) Is the v3_ext
parsing approach the only option and correct? b) Are there better options?
Since no one had an idea how to do it, I followed the approach to parse the v3_ext
field of the mbedtls_x509_crt
struct.
#include "mbedtls/x509_crt.h"
#include <mbedtls/oid.h>
#include "mbedtls/platform.h"
const uint8_t SKID[] = {0x55, 0x1D, 0x0E}; //!< Subject key identifer OID.
int load_skid(const char* path, uint8_t* skid[]) {
int err = 0;
mbedtls_x509_crt cert;
mbedtls_x509_buf buf;
mbedtls_asn1_sequence extns;
mbedtls_asn1_sequence *next;
memset(&extns, 0, sizeof(extns));
mbedtls_x509_crt_init(&cert);
size_t tag_len;
if (mbedtls_x509_crt_parse_file(&cert, path)) {
err = 1;
goto exit;
}
buf = cert.v3_ext;
if (mbedtls_asn1_get_sequence_of(&buf.p, buf.p + buf.len, &extns, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
err = 1;
goto exit;
}
next = &extns;
while (next) {
if (mbedtls_asn1_get_tag(&(next->buf.p), next->buf.p + next->buf.len, &tag_len, MBEDTLS_ASN1_OID)) {
err = 1;
goto exit;
}
if (!memcmp(next->buf.p, SKID, tag_len)) {
// get value
// correct length for SEQ TL + SKID OID value = 2 + tag_len
unsigned char *p = next->buf.p + tag_len;
if (mbedtls_asn1_get_tag(&p, p + next->buf.len-2-tag_len, &tag_len, MBEDTLS_ASN1_OCTET_STRING)) {
err = 1;
goto exit;
}
// include OCT TL = 2
if (mbedtls_asn1_get_tag(&p, p + next->buf.len-2, &tag_len, MBEDTLS_ASN1_OCTET_STRING)) {
err = 1;
goto exit;
}
if (tag_len != 20) {
err = 1;
goto exit;
}
memcpy(skid, p, 20);
goto exit;
}
next = next->next;
}
// skid not found
err = 1;
exit:
mbedtls_x509_crt_free(&cert);
mbedtls_asn1_sequence *cur;
next = extns.next;
while (next != NULL) {
cur = next;
next = next->next;
mbedtls_free(cur);
}
return err;
}