The following is the code to drive public keys from certificates and private key files, which are generated based on ECC curve MBEDTLS_ECP_DP_SECP521R1.
I like to put the correct public key into mbedtls_ecdh_context structures using mbedtls api functions. It is implemented with mbedtls v.3.3.0.
Where are mistakes in the following code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "mbedtls/platform.h"
#include "mbedtls/error.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/pk.h"
#include "mbedtls/x509_crt.h"
static void hexdump(void const *bptr, size_t bytes)
{
unsigned char *origin = (unsigned char *)(bptr);
unsigned block = 0x10;
size_t offset = 0;
size_t lower = block * (offset / block);
size_t upper = block + lower;
size_t index = 0;
char buffer[ADDRSIZE + 72];
char *output;
while (lower < bytes)
{
output = buffer + ADDRSIZE;
for (index = lower; output-- > buffer; index >>= 4)
{
*output = DIGITS_HEX[index & 0x0F];
}
output = buffer + ADDRSIZE;
for (index = lower; index < upper; index++)
{
*output++ = ' ';
if (index < offset)
{
*output++ = ' ';
*output++ = ' ';
}
else if (index < bytes)
{
*output++ = DIGITS_HEX[(origin[index] >> 4) & 0x0F];
*output++ = DIGITS_HEX[(origin[index] >> 0) & 0x0F];
}
else
{
*output++ = ' ';
*output++ = ' ';
}
}
*output++ = ' ';
for (index = lower; index < upper; index++)
{
if (index < offset)
{
*output++ = ' ';
}
else if (index < bytes)
{
unsigned c = origin[index];
*output++ = isprint(c) ? c : '.';
}
else
{
*output++ = ' ';
}
}
*output++ = '\n';
*output++ = '\0';
printf("%s", buffer);
// fputs (buffer, stdout);
lower += block;
upper += block;
}
if (bytes)
{
output = buffer;
*output++ = '\n';
*output++ = '\0';
printf("%s", buffer);
// fputs (buffer, stdout);
}
// fflush (stdout);
return;
}
int main(int argc, char *argv[])
{
mbedtls_ecdh_context ctx_bob, ctx_pub_bob;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_pk_context pk_bob;
mbedtls_x509_crt crt_bob;
int ret;
mbedtls_ecdh_init(&ctx_bob);
mbedtls_ecdh_init(&ctx_pub_bob);
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_pk_init(&pk_bob);
mbedtls_x509_crt_init(&crt_bob);
// Initialize RNG and entropy source
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0)
{
mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%04X\n", -ret);
goto cleanup;
}
if ((ret = mbedtls_pk_parse_keyfile(&pk_bob, KEY_FILE, NULL, mbedtls_ctr_drbg_random, &ctr_drbg)) != 0)
{
mbedtls_printf(" failed\n ! mbedtls_pk_parse_keyfile returned -0x%04X\n", -ret);
goto cleanup;
}
mbedtls_ecp_keypair *bob_keypair = mbedtls_pk_ec(pk_bob);
if ((ret = mbedtls_ecdh_get_params(&ctx_bob, bob_keypair, MBEDTLS_ECDH_OURS)) != 0)
{
mbedtls_printf(" failed\n ! mbedtls_ecdh_get_params returned -0x%04X\n", -ret);
goto cleanup;
}
if ((ret = mbedtls_ecdh_gen_public(&ctx_bob.grp, &ctx_bob.d, &ctx_bob.Q, mbedtls_ctr_drbg_random, &ctr_drbg)) != 0)
{
mbedtls_printf(" failed\n ! mbedtls_ecdh_make_public returned -0x%04X\n", -ret);
goto cleanup;
}
// Exchange public keys between SA and EVCC
// In a real-world scenario, this would be done over a communication channel
// Here we just simulate it by copying the public keys to each other's context
// EVCC Public Key Context
if ((ret = mbedtls_x509_crt_parse_file(&crt_bob, CRTIFICATE_FILE)) != 0)
{
mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse_file returned -0x%04X\n", -ret);
goto cleanup;
}
mbedtls_ecp_keypair *bob_pub_keypair = mbedtls_pk_ec(crt_bob.pk);
if ((ret = mbedtls_ecdh_get_params(&ctx_pub_bob, bob_pub_keypair, MBEDTLS_ECDH_OURS)) != 0)
{
mbedtls_printf("%d: failed\n ! mbedtls_ecdh_get_params returned -0x%04X\n", __LINE__, -ret);
goto cleanup;
}
printf("%d: ctx_bob public key\n", __LINE__);
printf("%d: d\n", __LINE__);
hexdump(&ctx_bob.d, sizeof(mbedtls_mpi));
printf("%d: Q\n", __LINE__);
hexdump(&ctx_bob.Q, sizeof(mbedtls_ecp_point));
printf("%d: grp\n", __LINE__);
hexdump(&ctx_bob.grp, sizeof(mbedtls_ecp_group));
printf("%d: ctx_pub_bob public key\n", __LINE__);
printf("%d: d\n", __LINE__);
hexdump(&ctx_pub_bob.d, sizeof(mbedtls_mpi));
printf("%d: Q\n", __LINE__);
hexdump(&ctx_pub_bob.Q, sizeof(mbedtls_ecp_point));
printf("%d: grp\n", __LINE__);
hexdump(&ctx_pub_bob.grp, sizeof(mbedtls_ecp_group));
cleanup:
mbedtls_ecdh_free(&ctx_bob);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_pk_free(&pk_bob);
mbedtls_x509_crt_free(&crt_bob);
return 0;
}
Two public keys ctx_bob.Q and ctx_pub_bob.Q printed out should be equal.