Using X509 certificates

Hello,

I am using NRF5340-DK for my project and I wanted to know if there is some example on how to read and extract the public key from this type of certificate. I have read something about mbedtls library but did not find any example. Is there some example that can help me?

BR.

  • Hello,

    In nRF Connect SDK, PEM is supported with the Nordic Security (mbedTLS) backend, you can look at AWS IoT sample to see how to use it.

    You can look at this previous case (+) Nordic DevZone

  • Hello,

    If you want the key in the DER format for later verifications of the generated JWT, use the CONFIG_APP_JWT_PRINT_EXPORTED_PUBKEY_DER Kconfig option that prints the DER-formatted key to the debug terminal. You can convert the DER key into PEM format by encoding it in base64 and adding the PEM markers -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY-----.

    source: Application JWT

  • I will leave this code here for anyone interested. It can verify and extract public key from X509 DER certificates.

    #include <zephyr/kernel.h>
    #include <stdio.h>
    
    #include "mbedtls/x509_crt.h"
    #include "mbedtls/pk.h"
    #include "mbedtls/ctr_drbg.h"
    #include "mbedtls/entropy.h"
    
    const unsigned char cert_der[] = {
      0x30, 0x82, 0x01, 0xf2, 0x30, 0x82, 0x01, 0x97, 0xa0, 0x03, 0x02, 0x01,
      0x02, 0x02, 0x14, 0x20, 0x8b, 0xaf, 0xbf, 0x1d, 0x3a, 0x20, 0x79, 0xcd,
      0xcb, 0x64, 0x95, 0x85, 0x5e, 0x5e, 0xb3, 0x2d, 0x51, 0x1d, 0xe0, 0x30,
      0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
      0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
      0x50, 0x54, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
      0x05, 0x42, 0x72, 0x61, 0x67, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
      0x55, 0x04, 0x07, 0x0c, 0x09, 0x47, 0x75, 0x69, 0x6d, 0x61, 0x72, 0x61,
      0x65, 0x73, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
      0x03, 0x44, 0x54, 0x78, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04,
      0x03, 0x0c, 0x04, 0x4a, 0x6f, 0x73, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32,
      0x35, 0x30, 0x39, 0x31, 0x31, 0x30, 0x39, 0x30, 0x31, 0x35, 0x39, 0x5a,
      0x17, 0x0d, 0x32, 0x36, 0x30, 0x39, 0x31, 0x31, 0x30, 0x39, 0x30, 0x31,
      0x35, 0x39, 0x5a, 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
      0x04, 0x06, 0x13, 0x02, 0x50, 0x54, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03,
      0x55, 0x04, 0x08, 0x0c, 0x05, 0x42, 0x72, 0x61, 0x67, 0x61, 0x31, 0x12,
      0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x47, 0x75, 0x69,
      0x6d, 0x61, 0x72, 0x61, 0x65, 0x73, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03,
      0x55, 0x04, 0x0a, 0x0c, 0x03, 0x44, 0x54, 0x78, 0x31, 0x0d, 0x30, 0x0b,
      0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x04, 0x4a, 0x6f, 0x73, 0x65, 0x30,
      0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
      0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
      0x00, 0x04, 0x3d, 0xf7, 0x62, 0xb2, 0xef, 0x4e, 0xc1, 0x5b, 0xc5, 0xe7,
      0x13, 0x09, 0x3d, 0x7d, 0x4c, 0x6c, 0x8d, 0x25, 0x3b, 0x19, 0xd6, 0xa0,
      0x5c, 0xfa, 0xac, 0x55, 0x1c, 0xc5, 0x4e, 0x28, 0xbd, 0xea, 0x49, 0x56,
      0x23, 0xe3, 0xa0, 0x34, 0xf6, 0xeb, 0x70, 0x59, 0x62, 0x54, 0x41, 0xcc,
      0xcf, 0x57, 0x48, 0x5d, 0x18, 0xa2, 0x02, 0xd3, 0xc2, 0x0d, 0xba, 0xdc,
      0x4a, 0x8b, 0x8d, 0x58, 0x47, 0x62, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d,
      0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7e, 0xfd, 0x9a,
      0x52, 0x1f, 0x19, 0xa0, 0x70, 0xd9, 0x89, 0x69, 0xaa, 0x3e, 0x94, 0x94,
      0xad, 0x74, 0x9c, 0x4f, 0xce, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
      0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x7e, 0xfd, 0x9a, 0x52, 0x1f, 0x19,
      0xa0, 0x70, 0xd9, 0x89, 0x69, 0xaa, 0x3e, 0x94, 0x94, 0xad, 0x74, 0x9c,
      0x4f, 0xce, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
      0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a,
      0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46,
      0x02, 0x21, 0x00, 0xb4, 0x16, 0x73, 0xac, 0x73, 0xb0, 0xa3, 0x00, 0xd9,
      0x77, 0x05, 0xc6, 0x25, 0xe7, 0x94, 0x76, 0x53, 0xd4, 0xc6, 0x8e, 0x6a,
      0xb4, 0x71, 0x9d, 0x21, 0xa5, 0x89, 0x85, 0x2f, 0xe4, 0x93, 0xf8, 0x02,
      0x21, 0x00, 0xed, 0xdd, 0xfe, 0x29, 0xdc, 0xb6, 0xb0, 0xce, 0x24, 0xf2,
      0xab, 0x42, 0x49, 0xed, 0xe8, 0xfe, 0xf9, 0xd5, 0xbb, 0x57, 0x93, 0x24,
      0x1b, 0x32, 0x37, 0xd2, 0x49, 0x5d, 0x83, 0xc8, 0x3f, 0xd1
    };
    
    const unsigned int cert_der_len = 502;
    
    int main(void)
    {
        printk("Start X509 test\n");
        
        int ret;
        mbedtls_x509_crt cert;
        mbedtls_x509_crt_init(&cert);
    
        /* Load certificate from DER array */
        ret = mbedtls_x509_crt_parse_der(&cert, cert_der, cert_der_len);
        if (ret < 0) 
        {
            printk("Failed to parse certificate (err %d)\n", ret);
            return -1;
        }
    
        // Verify self-signed certificate (no RNG)
        uint32_t flags = 0;
        ret = mbedtls_x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
        if (ret == 0 && flags == 0) {
            printk("Certificate signature is VALID (self-signed)\n");
        } else {
            printk("Certificate verification FAILED, ret=%d, flags=0x%08x\n", ret, flags);
        }
    
        // Extract and print public key (optional)
        mbedtls_pk_context *pk = &cert.pk;
        if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) 
        {
            mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
            const mbedtls_ecp_point *Q = &ec->MBEDTLS_PRIVATE(Q);
    
            char buf[100]; // safe buffer
            size_t olen;
    
            // Print X
            ret = mbedtls_mpi_write_string(&Q->MBEDTLS_PRIVATE(X), 16, buf, sizeof(buf), &olen);
            if (ret == 0) {
                printk("Public key X: 0x%s\n", buf);
            } else {
                printk("Error printing X: %d\n", ret);
            }
    
            // Print Y
            ret = mbedtls_mpi_write_string(&Q->MBEDTLS_PRIVATE(Y), 16, buf, sizeof(buf), &olen);
            if (ret == 0) {
                printk("Public key Y: 0x%s\n", buf);
            } else {
                printk("Error printing Y: %d\n", ret);
            }
        }
       
        mbedtls_x509_crt_free(&cert);
    
        return 0;
    }

Related