Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When adding a custom extension to a certificate using mbedtls, setting the critical flag to 1 results in the following error: -0x2562: X509 - The extension tag or value is invalid : ASN1 - ASN1 tag was of an unexpected value #9417

Closed
ranbi666 opened this issue Jul 23, 2024 · 1 comment

Comments

@ranbi666
Copy link

Describe the issue

When adding a custom extension to a certificate using mbedtls, setting the critical flag to 1 results in the following error:
-0x2562: X509 - The extension tag or value is invalid : ASN1 - ASN1 tag was of an unexpected value

Steps to Reproduce

  1. Attempt to add a custom extension to a certificate using mbedtls.
  2. Set the critical flag to 1.
  3. Encounter the error during certificate generation.

Example Code

#include "mbedtls/build_info.h"

#include "mbedtls/platform.h"

#include "mbedtls/x509_csr.h"
#include "mbedtls/pk.h"
#include "mbedtls/oid.h"
#include "mbedtls/ecp.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/ecdh.h"
#include <mbedtls/base64.h>

int nfi_generate_ecc_key_pair(mbedtls_pk_context *key) {
    int ret;
    mbedtls_entropy_context entropy; 
    mbedtls_ctr_drbg_context ctr_drbg; 

  
    const char *pers = "";

   
    mbedtls_pk_init(key);

    mbedtls_entropy_init(&entropy);


    mbedtls_ctr_drbg_init(&ctr_drbg);

    if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0) 
    {
        mbedtls_entropy_free(&entropy); 
        return ret;
    }

    if ((ret = mbedtls_pk_setup(key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY))) != 0) 
    {
        
        mbedtls_ctr_drbg_free(&ctr_drbg); 
        mbedtls_entropy_free(&entropy); 
        return ret;
    }
    if ((ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*key), mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
        
        mbedtls_pk_free(key); 
        mbedtls_ctr_drbg_free(&ctr_drbg); 
        mbedtls_entropy_free(&entropy); 
        return ret;
    }

    mbedtls_entropy_free(&entropy);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    printf("Generating ECC key pair ok\n");
    return 0;
}

void nfi_set_certificate_validity(mbedtls_x509write_cert *crt_writer, int valid_days) {
    int ret;
    time_t now;
    struct tm *tm_info;
    char not_before[15];
    char not_after[15];

    now = time(NULL);
    tm_info = gmtime(&now);  


    strftime(not_before, sizeof(not_before), "%Y%m%d%H%M%S", tm_info);


    tm_info->tm_mday += valid_days;
    mktime(tm_info);  

    strftime(not_after, sizeof(not_after), "%Y%m%d%H%M%S", tm_info);


    ret = mbedtls_x509write_crt_set_validity(crt_writer, not_before, not_after);
    if (ret != 0) {
        printf("Failed to set certificate validity: -0x%x\n", -ret);
    } else {
        printf("Certificate validity set from %s to %s\n", not_before, not_after);
    }
}

void add_extension(mbedtls_x509write_cert *crt, const char *oid, const char *value, int critical) {
    int ret;
    
    unsigned char buf[128];
    unsigned char *p = buf + sizeof(buf);
    ret = mbedtls_asn1_write_octet_string(&p, buf, value, strlen(value));
    if (ret <= 0) 
    {
        printf("Failed to add mbedtls_asn1_write_octet_string: -0x%x\n", -ret);
    }

    int ext_valueLen = ret;

    mbedtls_asn1_buf oidASN;
    ret = mbedtls_oid_from_numeric_string(&oidASN, oid, strlen(oid));
    if (ret != 0) {
        printf("Failed to mbedtls_oid_from_numeric_string: -0x%x\n", -ret);
    }

    ret = mbedtls_x509write_crt_set_extension(crt, oidASN.p, oidASN.len, critical,p,ext_valueLen);
    if (ret != 0) {
        printf("Failed to add extension: -0x%x\n", -ret);
    }
    else
    {
        printf("add extension OK1\n");
    }
}


int main()
{
  mbedtls_x509_crt crt;
  mbedtls_pk_context key;

  nfi_generate_ecc_key_pair(&key);
  int ret;
  mbedtls_mpi serial;
  mbedtls_x509write_cert crt_writer;
  mbedtls_entropy_context entropy;
  mbedtls_ctr_drbg_context ctr_drbg;
  const char *pers = "crt_gen";
  uint8_t *subject_namem = "CN=TestCN";

  mbedtls_x509write_crt_init(&crt_writer);
  mbedtls_mpi_init(&serial);
  mbedtls_x509_crt_init(&crt);

  mbedtls_entropy_init(&entropy);
  mbedtls_ctr_drbg_init(&ctr_drbg);

  if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0) {
      return ret;
  }

  if ((ret = mbedtls_mpi_read_string(&serial, 10, "1")) != 0) {
      return ret;
  }

  mbedtls_x509write_crt_set_serial(&crt_writer, &serial);
  nfi_set_certificate_validity(&crt_writer,365);
  mbedtls_x509write_crt_set_subject_key(&crt_writer, &key);
  mbedtls_x509write_crt_set_issuer_key(&crt_writer, &key);
  mbedtls_x509write_crt_set_md_alg(&crt_writer, MBEDTLS_MD_SHA256);
  
  if ((ret = mbedtls_x509write_crt_set_subject_name(&crt_writer, subject_namem)) != 0) {
      return ret;
  }

  if ((ret = mbedtls_x509write_crt_set_issuer_name(&crt_writer, subject_namem)) != 0) {
      return ret;
  }
  
  mbedtls_x509write_crt_set_basic_constraints(&crt_writer, 1, 0);
  mbedtls_x509write_crt_set_key_usage(&crt_writer, MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
                                                  MBEDTLS_X509_KU_NON_REPUDIATION   |
                                                  MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
                                                  MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
                                                  MBEDTLS_X509_KU_KEY_AGREEMENT     |
                                                  MBEDTLS_X509_KU_KEY_CERT_SIGN     |
                                                  MBEDTLS_X509_KU_CRL_SIGN          |
                                                  MBEDTLS_X509_KU_ENCIPHER_ONLY     |
                                                  MBEDTLS_X509_KU_DECIPHER_ONLY     );

  add_extension(&crt_writer,"1.3.2.5.444.2.1","0123",1);

  unsigned char output_buf[4096];
  memset(output_buf, 0, sizeof(output_buf));
  ret = mbedtls_x509write_crt_pem(&crt_writer, output_buf, sizeof(output_buf), mbedtls_ctr_drbg_random, &ctr_drbg);
  if (ret < 0) {
      return ret;
  }

  ret = mbedtls_x509_crt_parse(&crt, output_buf, sizeof(output_buf));
  if (ret < 0) {
      return ret;
  }

  memset(output_buf, 0, sizeof(output_buf));
  ret = mbedtls_x509write_crt_der(&crt_writer,output_buf, sizeof(output_buf), mbedtls_ctr_drbg_random, &ctr_drbg);

  printf("der Len [%d]\n",ret);
  for (size_t i = 0; i < ret; i++)
  {
    printf("%02x", output_buf[sizeof(output_buf) - ret + i]);
  }
  printf("\n");

  mbedtls_mpi_free(&serial);
  mbedtls_x509write_crt_free(&crt_writer);
  mbedtls_entropy_free(&entropy);
  mbedtls_ctr_drbg_free(&ctr_drbg);

  return 0;
}
@ranbi666 ranbi666 closed this as not planned Won't fix, can't repro, duplicate, stale Jul 23, 2024
@ChrisGan0831
Copy link

1 mbedtls_x509write_crt_pem -》mbedtls_x509write_crt_der
2 mbedtls_x509_crt_parse-》 mbedtls_x509_crt_parse_der_with_ext_cb it can resolve unsupported critical extension question
(Remove the MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION config.h option. The mbedtls_x509_crt_parse_der_with_ext_cb() is the way to go for migration path. Fixes #4378.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants