Search code examples
x509mbedtls

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?


Solution

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