Jeremy
Jeremy

Reputation: 1143

mbedtls: How to transfer and load public key as raw bytes

I want to use a public/private key pair (ECDSA using secp256r1 curve) to sign commands sent to an embedded device via BLE, and verify them on the device. This means sending the public key to the embedded device (during registration) and storing the public key on the device. When a command is received by the device, the public key is used to verify the signature with mbedtls.

To keep things simple and efficient, I thought it would be best to send and store the uncompressed 64 byte data from the public key (i.e. x and y co-ordinates).

I can generate a key pair and extract the 64 bytes of the public key in my Android app, and send these to the device using BLE.

However, I haven't found a good way to use this public key data to verify signatures with embedtls - i.e. to load the raw 64 bytes into a suitable mbedtls_ecp_keypair struct.

I have been able to do it with "mbedtls_ecp_point_read_string" as follows (error checking removed for brevity):

// public_key_data is buffer containing 64 bytes (32 bytes X, 32 bytes Y).

mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa);

mbedtls_ecp_keypair public_key;
mbedtls_ecp_keypair_init(&public_key);

mbedtls_ecp_point_init(&public_key.Q);

mbedtls_ecp_group_init(&public_key.grp);
mbedtls_ecp_group_load(&public_key.grp, MBEDTLS_ECP_DP_SECP256R1);

// Convert raw bytes of public key (public_key_data) to ASCII string (hex format).
// BytesToHexStr is C function to convert bytes to string:
char x_str[65]; // 2 x 32 bytes + 1 byte for terminating NUL
char y_str[65];
BytesToHexStr(public_key_data, x_str, ...);
BytesToHexStr(public_key_data + 32, y_str, ...);

// Get ECP point from string...
mbedtls_ecp_point_read_string(
    &public_key.Q,   // mbedtls_ecp_point *P,
    16,                  // int radix,
    x_str,               // const char *x,
    y_str                // const char *y 
);

mbedtls_ecdsa_from_keypair(&ecdsa, &public_key);

// Generate hash of message:
mbedtls_sha256_ret(message, message_size, hash, SHA_256);

// Verify signature:
int verify_result = mbedtls_ecdsa_read_signature(&ecdsa, hash, sizeof(hash), signature, signature_size);

// Check verify_result, clean up, etc.

However, this seems cumbersome.

I tried using the "mbedtls_ecp_point_read_binary" function with my raw public key, but it returned -20096 (MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE). The mbedtls documentation says "This function imports a point from unsigned binary data", but it doesn't give any details about what format the data is expected to be in.

Is there a better way to transfer / store / load ECDSA public key data with mbedtls?

Upvotes: 3

Views: 4473

Answers (2)

Papyrus
Papyrus

Reputation: 329

If you've found this post for a similar but slightly different situation in that you are trying to use mbedtls_ecp_point_read_binary to read in your peer's public key (for ECDSA or ECDH key exchange for example), however your peer has only sent a compressed public key (33 bytes), there's a solution for this but it's limited to only a certain set of curves in mbedtls.

If you try mbedtls_ecp_point_read_binary to read in your peer's public key in compressed format you'll get a 0x4F80 (MBEDTLS_ERR_ECP_BAD_INPUT_DATA) error. The issue is exactly what @regnarts says (you need a decompressed key).

The challenge is that mbedtls doesn't support key decompression. Only tangentially related here but you can read into why that is here and here. Long story short, what emerged was a handy library (see link below) that correctly decompresses a key in binary format for a limited set of curves. Because it only supports those limited set of curves it wasn't incorporated into mbedtls, but it solved my problem so it's worth trying.

https://github.com/mwarning/mbedtls_ecp_compression

Upvotes: 1

regnarts
regnarts

Reputation: 56

I faced the exact same problem today. Eventually figured out that mbedtls_ecp_point_read_binary expects binary data in uncompressed public key format, i.e 0x04 followed by X followed by Y.

Upvotes: 4

Related Questions