Extracting Public key from the signed certificate

Hi I am trying to extract the public key from the below signed certificate received in memory, from the server. Now I have tried to extract the public key using

 ----- BEGIN BLOCK DATA -----
 /QIAADCCAvUwggKboAMCAQICCCCbF5IJGbo6MAoGCCqGSM49BAMCMFkxCzA
 JBgNVBAYTAlVTMSUwIwYDVQQKDBxIb25leXdlbGwgSW50ZXJuYXRpb25hbC
 BJbmMuMQwwCgYDVQQLDANBQ1MxFTATBgNVBAMMDFNoYXJlZCBRQSBDQTAgF
 w0xODEyMDUwNjE4NTBaGA85OTk5MDIwMTAwMDAwMFowXTELMAkGA1UEBhMC
 VVMxJTAjBgNVBAoTHEhvbmV5d2VsbCBJbnRlcm5hdGlvbmFsIEluYy4xDDA
 KBgNVBAsTA0hCVDEZMBcGA1UEAxMQSVJNTjQtQ29udHJvbGxlcjBZMBMGBy
 qGSM49AgEGCCqGSM49AwEHA0IABBVx/MplfIo9MH9Y6sZcPPOuJayHxuBKC
 o7DEbLA/ChS99uyO6q+Lo3ik75CuU8dGtRQBMwNALtofVtGW8VzJtyjggFF
 MIIBQTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFIoKOx1wakkJN2+NAMX
 fIahFb64NMDwGCCsGAQUFBwEBBDAwLjAsBggrBgEFBQcwAYYgaHR0cDovL3
 FocHBraS5ob25leXdlbGwuY29tL29jc3AwSQYDVR0gBEIwQDA+BgwrBgEEA
 YGkBgIBAQEwLjAsBggrBgEFBQcCARYgaHR0cHM6Ly9xaHBwa2kuaG9uZXl3
 ZWxsLmNvbS9jcHMwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwQAYDVR0fBDk
 wNzA1oDOgMYYvaHR0cDovL3FocHBraS5ob25leXdlbGwuY29tL2NybC9TaG
 FyZWRRQUNBMi5jcmwwHQYDVR0OBBYEFA0eOtWYB7bCyivOv1RpdNIzYDOxM
 A4GA1UdDwEB/wQEAwIDiDAKBggqhkjOPQQDAgNIADBFAiBa2F0I+H1annJg
 8pLMPF+dr0q66iD0ILrVAwr0zn9B0QIhAJzjnQD6uUVhGMKEeml3C4DujSs
 b+0746rFJt8fKyqR5grESYg==
 ----- END BLOCK DATA -----

I have implemented the below code, to extract. But parsing itself is failing.

mbedtls_x509_crt cert_mbedtls_format;
mbedtls_x509_crt_init( &cert_mbedtls_format );
// mbedtls_pk_init( &key );
//
ret = mbedtls_x509_crt_parse( &cert_mbedtls_format,
rdata, //Contains the Base64 decoded certificate
4096 );
if ( ret != 0 )
{
return -1; //Code is failing here it self
}
// memcpy(publicKey, (unsigned char *)key.pk_info, (size_t)(key.pk_info));

ret = mbedtls_pk_parse_public_key( &cert_mbedtls_format.pk, publicKey, 1024 ); 

if( ret != 0 )
{
    mbedtls_printf( " failed\n  !  " );
   goto exit;
}

Please explain me once receiving the signed certificate (I hope it is Base64 decoded). How to extract the above certificate and get the public key.

Hi @aric

The data that you are trying to parse is not a signed X509 certtificate, nor a public key.

A signed certificate should have the header\footer: -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.

A public key should have -----BEGIN RSA PUBLIC KEY----- and -----END RSA PUBLIC KEY----- in PKCS#1 format ( or ECC key), and -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- in PKCS#8. These are the current supported PKCS formats.

I am not sure what ----- BEGIN BLOCK DATA ----- represents at the moment, and couldn’t find references for it.
Regards,
Mbed TLS Team member
Ron

Hi Ron Thank you very much for your reply. Apologies for pasting the wrong data in above post. Well below is the certificate that i have received from server:

-----BEGIN CERTIFICATE-----
/QIAADCCAvUwggKboAMCAQICCErf0AxyEP0CMAoGCCqGSM49BAMCMFkxCzA
JBgNVBAYTAlVTMSUwIwYDVQQKDBxIb25leXdlbGwgSW50ZXJuYXRpb25hbC
BJbmMuMQwwCgYDVQQLDANBQ1MxFTATBgNVBAMMDFNoYXJlZCBRQSBDQTAgF
w0xODEyMDcwNTM2MjFaGA85OTk5MDIwMTAwMDAwMFowXTELMAkGA1UEBhMC
VVMxJTAjBgNVBAoTHEhvbmV5d2VsbCBJbnRlcm5hdGlvbmFsIEluYy4xDDA
KBgNVBAsTA0hCVDEZMBcGA1UEAxMQSVJNTjQtQ29udHJvbGxlcjBZMBMGBy
qGSM49AgEGCCqGSM49AwEHA0IABKVlgTLnxtWiD2V223LBb7qIEapx+lxfW
b8Cb56PmvpThedacwm3UuCJKSS6Q5Ddv8qJYjdsH00ufauxiPmZPfajggFF
MIIBQTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFIoKOx1wakkJN2+NAMX
fIahFb64NMDwGCCsGAQUFBwEBBDAwLjAsBggrBgEFBQcwAYYgaHR0cDovL3
FocHBraS5ob25leXdlbGwuY29tL29jc3AwSQYDVR0gBEIwQDA+BgwrBgEEA
YGkBgIBAQEwLjAsBggrBgEFBQcCARYgaHR0cHM6Ly9xaHBwa2kuaG9uZXl3
ZWxsLmNvbS9jcHMwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwQAYDVR0fBDk
wNzA1oDOgMYYvaHR0cDovL3FocHBraS5ob25leXdlbGwuY29tL2NybC9TaG
FyZWRRQUNBMi5jcmwwHQYDVR0OBBYEFOuWjaS5cMsfy3QVoG4menUJW/VeM
A4GA1UdDwEB/wQEAwIDiDAKBggqhkjOPQQDAgNIADBFAiEA6DIAoIB5+onV
06WqLAuDCRcH1dQ6JsbYIUPBve3hSVUCIH7pilm++bCpRRD2cFSMjIWomzQ
tQaqR8A8jCSkZ14JNgxOw3A==
-----END CERTIFICATE-----

After receiving the above certificate, I am trying to parse the certificate

In mbedtls_x509_crt_parse function calling the below

ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );

returning -8576

Below is the implementation:

int certificate_request(int argc, char *argv)
{
int ret = 0;
mbedtls_pk_context key;
char buf[1024];
int i;
char *p, *q, *r;
mbedtls_x509_crt cert_mbedtls_format;
mbedtls_x509write_csr req;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const char *pers = “csr example app”;

mbedtls_x509write_csr_init( &req );
mbedtls_x509write_csr_set_md_alg( &req, MBEDTLS_MD_SHA256 );
mbedtls_pk_init( &key );
mbedtls_ctr_drbg_init( &ctr_drbg );
memset( buf, 0, sizeof( buf ) );
   
char *rdata = NULL;
uint32_t rlength = 0;
uint32_t crt_crc = 0;

rdata = (char *)malloc(4096);
if(rdata == NULL)
  goto exit;

rlength = (uint32_t )irmn4_rcv_blkdata32 ( rdata, 4096 );			

if(write_dev_crt_to_spi_flash( rdata, rlength) != 0)
{
    printf(" DEV Certificate SPI flash Updated Failed!!! \n");
}else
{
    printf(" DEV Certificate SPI flash Updated Sucess!!! \n");
}

/* To convet in to pem format */
char pem[4096] = {0};
size_t olen = 0;
ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
                              rdata,
                              rlength, pem, 4096, &olen ) ;  


char strg[1024] = {0}; 
printf("\n----------------------------------------------------------------\n");
for(int i=0; i< olen; i++)
{
    sprintf(strg, "%c", pem[i]);	//Contains the above signed certificate:
    printf(strg);
}
printf("\n----------------------------------------------------------------\n");


// Extract the signature, then verify the certificate against CA public key
mbedtls_x509_crt_init( &cert_mbedtls_format );

ret = mbedtls_x509_crt_parse( &cert_mbedtls_format, 
                                  (const unsigned char *)pem,
                                   olen );							
if ( ret != 0 )
{
    return -1;		// Failing in mbedtls_x509_crt_parse_der(); returning  -8576
} 

ret = mbedtls_pk_parse_public_key( &cert_mbedtls_format.pk, pem, olen ); 

if( ret != 0 )
{
    mbedtls_printf( " failed\n  !  " );
    goto exit;
}

Hi @aric
Thank you for sharing your code.
Is the data you received a certificate or a certificate request?

If you used the sample application strerror you would see the following:

programs/util/strerror -8576
Last error was: -0x2180 - X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected

PEM_BEGIN_CSR and PEM_END_CSR that you re sending for writing in PEM are -----BEGIN CERTIFICATE REQUEST----- and -----END CERTIFICATE REQUEST-----. Not -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- as in your example. BTW, you don’t need to convert ot PEM in order to parse the certificate.

If it is a certificate request, then generating a certificate through a certificate request is not done the way you did in your code.
However, I believe that you are trying to parse the certificate stored in your flash, for that, all you need to do, is read it from flash, and parse it to fill the cert_mbedtls_format context. once the context is parsed, the pk member is already set, and you don’t need to parse the public key, in addition that the data is not a public key, so parsing would fail.

I have tried parsing your certificate with other libraries, such as openssl, and it failed as well.

I am having trouble understanding what you are trying to achieve in your example. Is irmn4_rcv_blkdata32 () receiving data from the network?

Regards,
Mbed TLS Team member
Ron

Hi Ron thank you very much, for your reply. Well actually I am trying to extract the public key from the received certificate. Below some more Information I am providing.

(1). Below is the raw certificate
-----BEGIN CERTIFICATE-----
MIIC9jCCAp2gAwIBAgIIWOYPeqhDmk0wCgYIKoZIzj0EAwIwWTELMAkGA1UEBhMC
VVMxJTAjBgNVBAoMHEhvbmV5d2VsbCBJbnRlcm5hdGlvbmFsIEluYy4xDDAKBgNV
BAsMA0FDUzEVMBMGA1UEAwwMU2hhcmVkIFFBIENBMCAXDTE4MTIxMTA0NDIzNloY
Dzk5OTkwMjAxMDAwMDAwWjBfMQswCQYDVQQGEwJVUzElMCMGA1UEChMcSG9uZXl3
ZWxsIEludGVybmF0aW9uYWwgSW5jLjEMMAoGA1UECxMDSEJUMRswGQYDVQQDExJJ
Uk1ONC0wMEMwNDAwRjNBNTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATruzPw
jdrn54gQw5el+v3gHxpEg3pnE2+Bpa7UoB9OLp94lZCf0z2iCMxyv1yRah7eQv/c
WdFwW4jC5kkQ2Rlvo4IBRTCCAUEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSK
CjsdcGpJCTdvjQDF3yGoRW+uDTA8BggrBgEFBQcBAQQwMC4wLAYIKwYBBQUHMAGG
IGh0dHA6Ly9xaHBwa2kuaG9uZXl3ZWxsLmNvbS9vY3NwMEkGA1UdIARCMEAwPgYM
KwYBBAGBpAYCAQEBMC4wLAYIKwYBBQUHAgEWIGh0dHBzOi8vcWhwcGtpLmhvbmV5
d2VsbC5jb20vY3BzMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMEAGA1UdHwQ5MDcw
NaAzoDGGL2h0dHA6Ly9xaHBwa2kuaG9uZXl3ZWxsLmNvbS9jcmwvU2hhcmVkUUFD
QTIuY3JsMB0GA1UdDgQWBBQ06Ak10XmBw2Bk4+2enQk3ObANfTAOBgNVHQ8BAf8E
BAMCA4gwCgYIKoZIzj0EAwIDRwAwRAIgFfUQe+XZD6+9KHKhqrqTIe0+acHDymra
I+Zxicb2jjACIAhrSZjWC8RUY+jbHlaSntsdKatVdhGbweIu2cwvRDPS
-----END CERTIFICATE-----

(2). Server after Base64 encoding and calculating the CRC sending the
below to the controller (This is the certificate that i have shared in above post)

-----BEGIN CERTIFICATE-----
/gIAADCCAvYwggKdoAMCAQICCFjmD3qoQ5pNMAoGCCqGSM49BAMCMFkxCzA
JBgNVBAYTAlVTMSUwIwYDVQQKDBxIb25leXdlbGwgSW50ZXJuYXRpb25hbC
BJbmMuMQwwCgYDVQQLDANBQ1MxFTATBgNVBAMMDFNoYXJlZCBRQSBDQTAgF
w0xODEyMTEwNDQyMzZaGA85OTk5MDIwMTAwMDAwMFowXzELMAkGA1UEBhMC
VVMxJTAjBgNVBAoTHEhvbmV5d2VsbCBJbnRlcm5hdGlvbmFsIEluYy4xDDA
KBgNVBAsTA0hCVDEbMBkGA1UEAxMSSVJNTjQtMDBDMDQwMEYzQTUwMFkwEw
YHKoZIzj0CAQYIKoZIzj0DAQcDQgAE67sz8I3a5+eIEMOXpfr94B8aRIN6Z
xNvgaWu1KAfTi6feJWQn9M9ogjMcr9ckWoe3kL/3FnRcFuIwuZJENkZb6OC
AUUwggFBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUigo7HXBqSQk3b40
Axd8hqEVvrg0wPAYIKwYBBQUHAQEEMDAuMCwGCCsGAQUFBzABhiBodHRwOi
8vcWhwcGtpLmhvbmV5d2VsbC5jb20vb2NzcDBJBgNVHSAEQjBAMD4GDCsGA
QQBgaQGAgEBATAuMCwGCCsGAQUFBwIBFiBodHRwczovL3FocHBraS5ob25l
eXdlbGwuY29tL2NwczAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjBABgNVHR8
EOTA3MDWgM6Axhi9odHRwOi8vcWhwcGtpLmhvbmV5d2VsbC5jb20vY3JsL1
NoYXJlZFFBQ0EyLmNybDAdBgNVHQ4EFgQUNOgJNdF5gcNgZOPtnp0JNzmwD
X0wDgYDVR0PAQH/BAQDAgOIMAoGCCqGSM49BAMCA0cAMEQCIBX1EHvl2Q+v
vShyoaq6kyHtPmnBw8pq2iPmcYnG9o4wAiAIa0mY1gvEVGPo2x5Wkp7bHSm
rVXYRm8HiLtnML0Qz0p/aJjk=
-----END CERTIFICATE-----

There is some issue, in decoding (2). for time-being please ignore it. Consider the raw certificate (1)

From (1)
Using openssl I am able to extract the public key. It is working fine

/***********************************************************/

  1. Copy (1) and save as cert.pem
  2. OpenSSL command: OpenSSL> x509 -in cert.pem -text -noout
    /***********************************************************/


Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:eb:bb:33:f0:8d:da:e7:e7:88:10:c3:97:a5:fa:
fd:e0:1f:1a:44:83:7a:67:13:6f:81:a5:ae:d4:a0:
1f:4e:2e:9f:78:95:90:9f:d3:3d:a2:08:cc:72:bf:
5c:91:6a:1e:de:42:ff:dc:59:d1:70:5b:88:c2:e6:
49:10:d9:19:6f
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Authority Key Identifier:
keyid:8A:0A:3B:1D:70:6A:49:09:37:6F:8D:00:C5:DF:21:A8:45:6F:AE:0D



/***********************************************************/

But I am unable to extract the public key using mbedTLS library.

I would like to request you please have a look at the certificate (1)
And please help me using mbedTLS how to extract the public key?
Please give the example code or any working code snippet that work for me

Thanks,
Aric

Hi Aric,
Note that your openssl command is not extracting the public key, but printing the certificate information, public key being one of them.
The Mbed TLS cert_app doesn’t print the key data. However, once parse, the structure for mbedtls_x509_crt contains an encapsulated member pk of type mbedtls_pk_context. This is the parsed public key of the certificate. You can then use the pk member as you see. Note this is an internal member, and it is not guaranteed that it will remain the same name \ location in structure, etc… However, since there is no APi to extract it, it will do for now.
You can look at Mbedtls_pk_context handling - #2 by roneld01 for some hints.
May I know why you need the certificate public key outside of the certificate verification?
Regards,
Mbed TLS Team member
Ron

I have created API to extract public key from parsed certificate · Issue #2294 · Mbed-TLS/mbedtls · GitHub that should address this