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
- Attempt to add a custom extension to a certificate using mbedtls.
- Set the
critical
flag to1
. - 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 with_out(void *p_ctx,
mbedtls_x509_crt const *crt,
mbedtls_x509_buf const *oid,
int critical,
const unsigned char *p,
const unsigned char *end)
{
return 0;
}
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;
}