v0.1.0 - CYD firmware v0.0.2: algorithm-based API upgrade (all verbs, all algorithms), vendored Keccak/SHAKE + PSA ed25519/x25519 for IDF v5.4, Web Serial test page, CYD docs, Teensy 4.1 port plan (1TB SDXC OTP pad), brainstorming READMEs for BLE/IR/NFC/FPGA signer concepts
This commit is contained in:
@@ -10,9 +10,9 @@
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/ed25519.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#include "secp256k1.h"
|
||||
#include "secp256k1_extrakeys.h"
|
||||
@@ -381,18 +381,33 @@ int derive_ed25519_key(const uint8_t seed[64], uint32_t index,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The SLIP-0010 derived 32 bytes IS the ed25519 private key.
|
||||
* Use mbedtls to derive the public key. */
|
||||
/* The SLIP-0010 derived 32 bytes IS the ed25519 private key. */
|
||||
memcpy(privkey, derived_seed, 32);
|
||||
|
||||
/* mbedtls_ed25519_make_public: derive pub from priv */
|
||||
/* Note: mbedtls ed25519 API may vary by version. The ESP-IDF mbedtls
|
||||
* component provides mbedtls_ed25519_make_public (or via the PK API).
|
||||
* We use the low-level function if available. */
|
||||
int ret = mbedtls_ed25519_make_public((unsigned char *)pubkey, 32,
|
||||
(const unsigned char *)privkey, 32);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(KD_TAG, "ed25519 make_public failed: %d", ret);
|
||||
/* Derive the ed25519 public key via PSA crypto (IDF v5.x mbedtls has no
|
||||
* mbedtls_ed25519_make_public). Import the private key, export the pub. */
|
||||
psa_status_t status;
|
||||
psa_key_id_t key_id = 0;
|
||||
psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT;
|
||||
size_t pub_len = 0;
|
||||
|
||||
psa_crypto_init();
|
||||
psa_set_key_type(&attrs, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS));
|
||||
psa_set_key_bits(&attrs, 255);
|
||||
psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE);
|
||||
psa_set_key_algorithm(&attrs, PSA_ALG_PURE_EDDSA);
|
||||
|
||||
status = psa_import_key(&attrs, privkey, 32, &key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(KD_TAG, "ed25519 psa_import failed: %d", (int)status);
|
||||
memset(derived_seed, 0, sizeof(derived_seed));
|
||||
memset(privkey, 0, 32);
|
||||
return -1;
|
||||
}
|
||||
status = psa_export_public_key(key_id, pubkey, 32, &pub_len);
|
||||
psa_destroy_key(key_id);
|
||||
if (status != PSA_SUCCESS || pub_len != 32) {
|
||||
ESP_LOGE(KD_TAG, "ed25519 psa_export_public failed: %d", (int)status);
|
||||
memset(derived_seed, 0, sizeof(derived_seed));
|
||||
memset(privkey, 0, 32);
|
||||
return -1;
|
||||
@@ -402,20 +417,64 @@ int derive_ed25519_key(const uint8_t seed[64], uint32_t index,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ed25519 sign via PSA (PureEdDSA — signs the raw message, not pre-hashed). */
|
||||
int ed25519_sign32(const uint8_t privkey[32], const uint8_t msg32[32],
|
||||
uint8_t sig64[64]) {
|
||||
/* mbedtls_ed25519_sign: sign a message (not pre-hashed) */
|
||||
int ret = mbedtls_ed25519_sign((unsigned char *)sig64, 64,
|
||||
(const unsigned char *)msg32, 32,
|
||||
(const unsigned char *)privkey, 32,
|
||||
NULL, NULL);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(KD_TAG, "ed25519 sign failed: %d", ret);
|
||||
return ed25519_sign_msg(privkey, msg32, 32, sig64);
|
||||
}
|
||||
|
||||
int ed25519_sign_msg(const uint8_t privkey[32], const uint8_t *msg, size_t msg_len,
|
||||
uint8_t sig64[64]) {
|
||||
psa_status_t status;
|
||||
psa_key_id_t key_id = 0;
|
||||
psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT;
|
||||
size_t sig_len = 0;
|
||||
|
||||
psa_crypto_init();
|
||||
psa_set_key_type(&attrs, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS));
|
||||
psa_set_key_bits(&attrs, 255);
|
||||
psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_SIGN_MESSAGE);
|
||||
psa_set_key_algorithm(&attrs, PSA_ALG_PURE_EDDSA);
|
||||
|
||||
status = psa_import_key(&attrs, privkey, 32, &key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(KD_TAG, "ed25519 sign psa_import failed: %d", (int)status);
|
||||
return -1;
|
||||
}
|
||||
status = psa_sign_message(key_id, PSA_ALG_PURE_EDDSA,
|
||||
msg, msg_len, sig64, 64, &sig_len);
|
||||
psa_destroy_key(key_id);
|
||||
if (status != PSA_SUCCESS || sig_len != 64) {
|
||||
ESP_LOGE(KD_TAG, "ed25519 psa_sign_message failed: %d", (int)status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ed25519_verify_msg(const uint8_t *sig, size_t sig_len,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
const uint8_t pubkey[32]) {
|
||||
psa_status_t status;
|
||||
psa_key_id_t key_id = 0;
|
||||
psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
psa_crypto_init();
|
||||
psa_set_key_type(&attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS));
|
||||
psa_set_key_bits(&attrs, 255);
|
||||
psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_VERIFY_MESSAGE);
|
||||
psa_set_key_algorithm(&attrs, PSA_ALG_PURE_EDDSA);
|
||||
|
||||
status = psa_import_key(&attrs, pubkey, 32, &key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(KD_TAG, "ed25519 verify psa_import failed: %d", (int)status);
|
||||
return -1;
|
||||
}
|
||||
status = psa_verify_message(key_id, PSA_ALG_PURE_EDDSA,
|
||||
msg, msg_len, sig, sig_len);
|
||||
psa_destroy_key(key_id);
|
||||
return (status == PSA_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
|
||||
/* --- x25519 --- */
|
||||
|
||||
int derive_x25519_key(const uint8_t seed[64], uint32_t index,
|
||||
@@ -429,10 +488,10 @@ int derive_x25519_key(const uint8_t seed[64], uint32_t index,
|
||||
0u | BIP32_HARDENED_FLAG,
|
||||
};
|
||||
uint8_t derived_seed[32];
|
||||
mbedtls_ecp_group grp;
|
||||
mbedtls_mpi d;
|
||||
mbedtls_ecp_point Q;
|
||||
int ret;
|
||||
psa_status_t status;
|
||||
psa_key_id_t key_id = 0;
|
||||
psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT;
|
||||
size_t pub_len = 0;
|
||||
|
||||
if (seed == NULL || privkey == NULL || pubkey == NULL) {
|
||||
return -1;
|
||||
@@ -443,54 +502,30 @@ int derive_x25519_key(const uint8_t seed[64], uint32_t index,
|
||||
}
|
||||
|
||||
/* The SLIP-0010 derived 32 bytes IS the x25519 private key.
|
||||
* Clamp it per RFC 7748 and derive the public key via mbedtls ECDH. */
|
||||
* PSA imports it and exports the public key (PSA handles clamping). */
|
||||
memcpy(privkey, derived_seed, 32);
|
||||
memset(derived_seed, 0, sizeof(derived_seed));
|
||||
|
||||
/* x25519 clamping: priv[0] &= 248, priv[31] &= 127, priv[31] |= 64 */
|
||||
privkey[0] &= 248;
|
||||
privkey[31] &= 127;
|
||||
privkey[31] |= 64;
|
||||
psa_crypto_init();
|
||||
psa_set_key_type(&attrs, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY));
|
||||
psa_set_key_bits(&attrs, 255);
|
||||
psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE);
|
||||
psa_set_key_algorithm(&attrs, PSA_ALG_ECDH);
|
||||
|
||||
mbedtls_ecp_group_init(&grp);
|
||||
mbedtls_mpi_init(&d);
|
||||
mbedtls_ecp_point_init(&Q);
|
||||
|
||||
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(KD_TAG, "x25519 group load failed: %d", ret);
|
||||
goto cleanup;
|
||||
status = psa_import_key(&attrs, privkey, 32, &key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(KD_TAG, "x25519 psa_import failed: %d", (int)status);
|
||||
memset(privkey, 0, 32);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mbedtls_mpi_read_binary_le(d, privkey, 32);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(KD_TAG, "x25519 mpi read failed: %d", ret);
|
||||
goto cleanup;
|
||||
status = psa_export_public_key(key_id, pubkey, 32, &pub_len);
|
||||
psa_destroy_key(key_id);
|
||||
if (status != PSA_SUCCESS || pub_len != 32) {
|
||||
ESP_LOGE(KD_TAG, "x25519 psa_export_public failed: %d", (int)status);
|
||||
memset(privkey, 0, 32);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mbedtls_ecp_mul(&grp, &Q, d, &grp.G, NULL, NULL);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(KD_TAG, "x25519 ecp_mul failed: %d", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Serialize the public key as raw 32 bytes (little-endian) */
|
||||
{
|
||||
size_t olen = 0;
|
||||
ret = mbedtls_ecp_point_write_binary(&grp, &Q,
|
||||
MBEDTLS_ECP_PF_COMPRESSED,
|
||||
&olen, pubkey, 32);
|
||||
if (ret != 0 || olen != 32) {
|
||||
ESP_LOGE(KD_TAG, "x25519 pub serialize failed: %d", ret);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
mbedtls_mpi_free(&d);
|
||||
mbedtls_ecp_point_free(&Q);
|
||||
return (ret == 0) ? 0 : -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- ML-DSA-65 --- */
|
||||
|
||||
Reference in New Issue
Block a user