Description
Board
ESP32-C3-DevKitM-1
Device Description
official Espressif Board
Hardware Configuration
Nothing Connected , just bare devboard
Version
v2.0.8
IDE Name
Arduino IDE
Operating System
Windows 11 22h2
Flash frequency
40
PSRAM enabled
no
Upload speed
115200
Description
I first wrote mbedtls code in C and tested with corresponding dart code which reproduces the same shared secret.
In Arduino IDE the main compilation happens on provided gcc compiler so , the code actually works just fine with mbedtls_mpi_write_binary(),
mbedtls_mpi_read_binary(),
It just doesn't produce the intended shared secret .
in RHEL 8 , gcc 8.5.0, i used mbedtls_mpi_write_binary_le(),
mbedtls_mpi_read_binary_le(),
which produced actual intended shared key in both Dart and C program, However in specific case of arduino ide , if we use the
mbedtls_mpi_write_binary_le(),
mbedtls_mpi_read_binary_le(),
both calculating functions produce error which are
mbedtls_ecdh_calc_secret() and mbedtls_ecdh_compute_shared(),
Sketch
*/Arduino Side Code/*
#include <mbedtls/ecdh.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include "mbedtls/error.h"
unsigned char my_pubkey[32] = { 0 };
unsigned char my_privkey[32] = { 0 };
unsigned char server_pubkey[32] = {0};
unsigned char server_privkey[32] = {0};
unsigned char shared_secret[32] = { 0 };
unsigned char shared_secret2[32] = { 0 };
void printhex(unsigned char* array, int size) {
for (int i = 0; i < size ; i++) {
char str[3];
sprintf(str, "%02x", (int)array[i]);
Serial.print(str);
}
Serial.println("\n");
}
void swapEndianArray(unsigned char* ptrIn[], unsigned char * ptrOut[], int size) {
int i;
for (i = 0; i < size; i++) {
ptrOut[i] = ptrIn[size - i - 1];
}
return;
}
void genkeyx25519(unsigned char* pubkey, unsigned char* privkey) {
unsigned char my_pubkey[32] = {0};
unsigned char my_privkey[32] = {0};
mbedtls_ecdh_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
// generate the keys and save to buffer
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
mbedtls_ecdh_init(&ctx);
mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, 0, 0);
mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_CURVE25519);
mbedtls_ecdh_gen_public(&ctx.grp, &ctx.d, &ctx.Q, mbedtls_ctr_drbg_random, &ctr_drbg);
mbedtls_mpi_write_binary_le(&ctx.Q.X, my_pubkey, sizeof(my_pubkey));
mbedtls_mpi_write_binary_le(&ctx.d, my_privkey, sizeof(my_privkey));
memcpy(pubkey, my_pubkey, sizeof(my_pubkey));
memcpy(privkey, my_privkey, sizeof(my_privkey));
mbedtls_ecdh_free(&ctx);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
}
void calcsecretx25519(unsigned char * privkey, unsigned char * serverpubkey, unsigned char* sharedsecret) {
unsigned char my_privkey[32] = {0};
unsigned char server_pubkey[32] = {0};
unsigned char shared_secret[32] = {0};
unsigned char buffer[32] = {0};
char error_buf[100];
memcpy(my_privkey, privkey, sizeof(privkey));
memcpy(server_pubkey, serverpubkey, sizeof(serverpubkey));
int ret = 1;
mbedtls_ecdh_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
// generate the keys and save to buffer
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
mbedtls_ecdh_init(&ctx);
mbedtls_ctr_drbg_seed(
&ctr_drbg,
mbedtls_entropy_func,
&entropy,
0,
0
);
ret = mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_CURVE25519);
if (ret != 0) {
printf("error in group load");
ret = 0 ;
}
// read my private key
ret = mbedtls_mpi_read_binary_le(&ctx.d, my_privkey, sizeof(my_privkey));
if (ret != 0) {
printf("error in reading privkey");
ret = 0 ;
}
ret = mbedtls_mpi_lset(&ctx.Qp.Z, 1);
if (ret != 0) {
printf("error in mpi lset for secret");
ret = 0 ;
}
// read server key
ret = mbedtls_mpi_read_binary_le(&ctx.Qp.X, server_pubkey, sizeof(server_pubkey));
if (ret != 0) {
printf("error in reading pubkey\n");
ret = 0 ;
}
//generate shared secret
size_t olen;
ret = mbedtls_ecdh_calc_secret(&ctx, &olen, shared_secret, 32,mbedtls_ctr_drbg_random, &ctr_drbg);
if (ret != 0) {
printf("error in calculating secret\n");
mbedtls_strerror(ret, error_buf, sizeof(error_buf));
printf("Error message for error code %d: %s\n", ret, error_buf);
ret = 0 ;
}
mbedtls_mpi_write_binary_le(&ctx.z, buffer, sizeof(buffer));
printf("Secret buffer :");
for (size_t i = 0; i < sizeof(buffer); i++)
printf("%02X", buffer[i]);
printf("\n");
printf("Secret :");
for (size_t i = 0; i < sizeof(shared_secret); i++)
printf("%02X", shared_secret[i]);
printf("\n");
memcpy(sharedsecret, shared_secret, sizeof(shared_secret));
mbedtls_ecdh_free(&ctx);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
}
void setup() {
Serial.begin(115200);
// put your setup code here, to run once:
genkeyx25519(my_pubkey, my_privkey);
printf("PUBKEY: ");
for (size_t i = 0; i < sizeof(my_pubkey); i++)
printf("%02x", my_pubkey[i]);
printf("\n");
printf("Privkey: ");
for (size_t i = 0; i < sizeof(my_privkey); i++)
printf("%02x", my_privkey[i]);
printf("\n");
genkeyx25519(server_pubkey, server_privkey);
printf("Server PUBKEY: ");
for (size_t i = 0; i < sizeof(server_pubkey); i++)
printf("%02x", server_pubkey[i]);
printf("\n");
printf("Server Privkey: ");
for (size_t i = 0; i < sizeof(server_privkey); i++)
printf("%02x", server_privkey[i]);
printf("\n");
calcsecretx25519(my_privkey, server_pubkey, shared_secret);
printf("Secret :");
for (size_t i = 0; i < sizeof(shared_secret); i++)
printf("%02X", shared_secret[i]);
printf("\n");
calcsecretx25519(server_privkey, my_pubkey, shared_secret2);
printf("Server Secret :");
for (size_t i = 0; i < sizeof(shared_secret2); i++)
printf("%02X", shared_secret2[i]);
printf("\n");
}
void loop() {
// put your main code here, to run repeatedly:
}
*/ END/*
*/DART CODE/*
import 'package:cryptography/cryptography.dart';
import 'package:cryptography/dart.dart';
import 'dart:convert';
import 'dart:math';
import 'dart:io';
import 'dart:typed_data';
import "package:hex/hex.dart";
Future<void> main() async {
// Generate a key pair for Alice
final algorithm = X25519();
final aliceKeyPair = await algorithm.newKeyPair();
// Generate a key pair for Bob.
//
// In a real application, we will receive or know Bob's public key
// somehow.
print("Write the HEX PUBKEY :");
final hexPublicKey = stdin.readLineSync()!;
print("HEX PUBKEY : $hexPublicKey");
final publicKeyBytes = HEX.decode(hexPublicKey);
final bobKeyPair = await algorithm.newKeyPair();
final bobPublicKey = await bobKeyPair.extractPublicKey();
final publicKey = SimplePublicKey(publicKeyBytes, type: KeyPairType.x25519);
final hexPubKey = await aliceKeyPair.extractPublicKey();
final publickeybytes = hexPubKey.bytes;
final pubkey = uint8ListToHex(publickeybytes);
print("PUBLIC KEY: $pubkey");
// We can now calculate a shared secret.
final sharedSecret = await algorithm.sharedSecretKey(
keyPair: aliceKeyPair,
remotePublicKey: publicKey,
);
final sharedSecretBytes = await sharedSecret.extractBytes();
final hex = uint8ListToHex(sharedSecretBytes);
print("Shared Secret HEX : $hex");
print('Shared secret: $sharedSecretBytes');
}
String uint8ListToHex(List<int> uint8List) {
String hexString = '';
for (int byte in uint8List) {
// Convert the byte value to a hexadecimal string with 2 characters
String hexByte = byte.toRadixString(16).padLeft(2, '0');
hexString += hexByte;
}
return hexString;
}
*/Dart Code/*
Debug Message
ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5810,len:0x438
load:0x403cc710,len:0x91c
load:0x403ce710,len:0x25b0
entry 0x403cc710
PUBKEY: d1cf1e2c0eaea894cd556df1a20ad3bbbb95818b57bce5a90f3786abbc67246c
Privkey: 70625c0deabc8b43fe8cb15e7fd7b7178a28e3e6ceb76f7a5719f32f48bd2944
Server PUBKEY: 7983b2d2c9201f1ac0cfb328d093b25017c706865f0738945ba6c8857eb6893c
Server Privkey: d03a05f065300175edda18d31cebcbe96ee8fcf53bb084284af9f41ff8536364
error in calculating secret
Error message for error code -19584: ECP - Invalid private or public key
Secret buffer :0000000000000000000000000000000000000000000000000000000000000000
Secret :0000000000000000000000000000000000000000000000000000000000000000
Secret :0000000000000000000000000000000000000000000000000000000000000000
error in calculating secret
Error message for error code -19584: ECP - Invalid private or public key
Secret buffer :0000000000000000000000000000000000000000000000000000000000000000
Secret :0000000000000000000000000000000000000000000000000000000000000000
Server Secret :0000000000000000000000000000000000000000000000000000000000000000
Other Steps to Reproduce
it works just fine in x86_64 so i guess it is not a mbedtls specific problem, most probably the problem corresponds to compiler specific endianness issue or linking problems so i opened an issue here, any specific help would be great, the code maybe messy but logic is understandable. can you please help me out?
I have checked existing issues, online documentation and the Troubleshooting Guide
- I confirm I have checked existing issues, online documentation and Troubleshooting guide.