k_o_
k_o_

Reputation: 6298

read subject key identifier extension with mbedTLS

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_extbut 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_extparsing approach the only option and correct? b) Are there better options?

Upvotes: 1

Views: 347

Answers (1)

k_o_
k_o_

Reputation: 6298

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;
}

Upvotes: 1

Related Questions