Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [4.0.0]

### Changed
- `lt_ecc_ecdsa_sign` now expects a 32-byte hash instead of an arbitrary message - provided data are not hashed anymore.
Select a hash function (e.g., SHA256) which outputs 32 bytes (or pad/truncate the output accordingly).

### Added

### Fixed

### Removed

## [3.2.0]

### Changed
Expand Down
25 changes: 13 additions & 12 deletions include/libtropic.h
Original file line number Diff line number Diff line change
Expand Up @@ -549,21 +549,22 @@ lt_ret_t lt_ecc_key_read(lt_handle_t *h, const lt_ecc_slot_t ecc_slot, uint8_t *
lt_ret_t lt_ecc_key_erase(lt_handle_t *h, const lt_ecc_slot_t ecc_slot);

/**
* @brief Performs ECDSA sign of a message with a private ECC key stored in TROPIC01
* @brief Calculates ECDSA signature of a message hash (32 bytes) with a private ECC key stored in
* TROPIC01.
*
* @param h Handle for communication with TROPIC01
* @param ecc_slot Slot containing a private key, TR01_ECC_SLOT_0 - TR01_ECC_SLOT_31
* @param msg Buffer containing a message
* @param msg_len Length of the message
* @param rs Buffer for storing a signature in a form of R and S bytes (should always have
* length 64B)
* @param h Handle for communication with TROPIC01.
* @param ecc_slot Slot containing a private key, TR01_ECC_SLOT_0 - TR01_ECC_SLOT_31.
* @param msg_hash Buffer containing a 32-byte hash of the message to sign.
* @param msg_hash_len Length of the hash.
* @param rs Buffer for storing a signature in a form of R and S bytes (should always have
* length 64B).
*
* @retval LT_OK Function executed successfully
* @retval other Function did not execute successully, you might use lt_ret_verbose() to get
* verbose encoding of returned value
* @retval LT_OK Function executed successfully.
* @retval other Function did not execute successully, you might use lt_ret_verbose() to
* get verbose encoding of returned value.
*/
lt_ret_t lt_ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t ecc_slot, const uint8_t *msg,
const uint32_t msg_len, uint8_t *rs);
lt_ret_t lt_ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t ecc_slot, const uint8_t *msg_hash,
const uint32_t msg_hash_len, uint8_t *rs);

/**
* @brief Performs EdDSA sign of a message with a private ECC key stored in TROPIC01
Expand Down
16 changes: 8 additions & 8 deletions include/libtropic_l3.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,14 +462,14 @@ lt_ret_t lt_in__ecc_key_erase(lt_handle_t *h);
* @note Used for separate L3 communication, for more information read info
* at the top of this file.
*
* @param h Handle for communication with TROPIC01
* @param slot ECC key slot to use for signing
* @param msg Message to sign
* @param msg_len Length of the message
* @return LT_OK if success, otherwise returns other error code.
*/
lt_ret_t lt_out__ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t slot, const uint8_t *msg,
const uint32_t msg_len);
* @param h Handle for communication with TROPIC01.
* @param slot ECC key slot to use for signing.
* @param msg_hash Buffer containing a 32-byte hash of the message to sign.
* @param msg_hash_len Length of the hash.
* @return LT_OK if success, otherwise returns other error code.
*/
lt_ret_t lt_out__ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t slot, const uint8_t *msg_hash,
const uint32_t msg_hash_len);

/**
* @brief Decodes ECDSA_Sign result payload.
Expand Down
10 changes: 6 additions & 4 deletions src/libtropic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1337,17 +1337,19 @@ lt_ret_t lt_ecc_key_erase(lt_handle_t *h, const lt_ecc_slot_t ecc_slot)
return lt_in__ecc_key_erase(h);
}

lt_ret_t lt_ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t ecc_slot, const uint8_t *msg,
const uint32_t msg_len, uint8_t *rs)
lt_ret_t lt_ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t ecc_slot, const uint8_t *msg_hash,
const uint32_t msg_hash_len, uint8_t *rs)
{
if (!h || !msg || !rs || (ecc_slot > TR01_ECC_SLOT_31)) {
if (!h || !msg_hash || !rs || (ecc_slot > TR01_ECC_SLOT_31) ||
msg_hash_len != TR01_L3_ECDSA_SIGN_CMD_MSG_HASH_LEN) {
return LT_PARAM_ERR;
}

if (h->l3.session_status != LT_SECURE_SESSION_ON) {
return LT_HOST_NO_SESSION;
}

lt_ret_t ret = lt_out__ecc_ecdsa_sign(h, ecc_slot, msg, msg_len);
lt_ret_t ret = lt_out__ecc_ecdsa_sign(h, ecc_slot, msg_hash, msg_hash_len);
if (ret != LT_OK) {
return ret;
}
Expand Down
39 changes: 5 additions & 34 deletions src/libtropic_l3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1202,39 +1202,17 @@ lt_ret_t lt_in__ecc_key_erase(lt_handle_t *h)
return LT_OK;
}

lt_ret_t lt_out__ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t slot, const uint8_t *msg,
const uint32_t msg_len)
lt_ret_t lt_out__ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t slot, const uint8_t *msg_hash,
const uint32_t msg_hash_len)
{
if (!h || (slot > TR01_ECC_SLOT_31) || !msg) {
if (!h || (slot > TR01_ECC_SLOT_31) || !msg_hash ||
msg_hash_len != TR01_L3_ECDSA_SIGN_CMD_MSG_HASH_LEN) {
return LT_PARAM_ERR;
}
if (h->l3.session_status != LT_SECURE_SESSION_ON) {
return LT_HOST_NO_SESSION;
}

// Prepare hash of a message
uint8_t msg_hash[32] = {0};
lt_ret_t ret;
lt_ret_t ret_unused;

// Initialize SHA-256 context.
ret = lt_sha256_init(h->l3.crypto_ctx);
if (ret != LT_OK) {
return ret;
}
ret = lt_sha256_start(h->l3.crypto_ctx);
if (ret != LT_OK) {
goto sha256_cleanup;
}
ret = lt_sha256_update(h->l3.crypto_ctx, (uint8_t *)msg, msg_len);
if (ret != LT_OK) {
goto sha256_cleanup;
}
ret = lt_sha256_finish(h->l3.crypto_ctx, msg_hash);
if (ret != LT_OK) {
goto sha256_cleanup;
}

// Pointer to access l3 buffer when it contains command data
struct lt_l3_ecdsa_sign_cmd_t *p_l3_cmd = (struct lt_l3_ecdsa_sign_cmd_t *)h->l3.buff;

Expand All @@ -1244,14 +1222,7 @@ lt_ret_t lt_out__ecc_ecdsa_sign(lt_handle_t *h, const lt_ecc_slot_t slot, const
p_l3_cmd->slot = slot;
memcpy(p_l3_cmd->msg_hash, msg_hash, sizeof(p_l3_cmd->msg_hash));

ret = lt_l3_encrypt_request(&h->l3);

sha256_cleanup:
ret_unused = lt_sha256_deinit(h->l3.crypto_ctx);
lt_secure_memzero(msg_hash, sizeof(msg_hash));
LT_UNUSED(ret_unused);

return ret;
return lt_l3_encrypt_request(&h->l3);
}

lt_ret_t lt_in__ecc_ecdsa_sign(lt_handle_t *h, uint8_t *rs)
Expand Down
4 changes: 3 additions & 1 deletion src/lt_l3_api_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,8 @@ LT_STATIC_ASSERT(
#define TR01_L3_ECDSA_SIGN_CMD_ID 0x70
/** @brief Command length (fields: CMD_ID + CMD_DATA) */
#define TR01_L3_ECDSA_SIGN_CMD_SIZE 48u
/** @brief Length of the msg_hash field */
#define TR01_L3_ECDSA_SIGN_CMD_MSG_HASH_LEN 32u

/** @brief Result length (fields: RESULT + RES_DATA) */
#define TR01_L3_ECDSA_SIGN_RES_SIZE 80u
Expand Down Expand Up @@ -1230,7 +1232,7 @@ struct lt_l3_ecdsa_sign_cmd_t {
* @brief
* The hash of the message to sign (max size of 32 bytes).
*/
uint8_t msg_hash[32]; /**< Hash of the Message to sign. */
uint8_t msg_hash[TR01_L3_ECDSA_SIGN_CMD_MSG_HASH_LEN]; /**< Hash of the Message to sign. */
} __attribute__((packed));

// clang-format off
Expand Down
17 changes: 9 additions & 8 deletions tests/functional/src/libtropic_functional_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ void lt_test_rev_eddsa_sign(lt_handle_t *h);
* Test steps:
* 1. Start Secure Session with pairing key slot 0.
* 2. Generate random message with random size for signing.
* 3. Sign message with each empty slot and check for fail.
* 4. Store pre-generated private key to each slot.
* 5. Read the public key from each slot.
* 6. Sign the message with each slot.
* 7. Verify the signature.
* 8. Erase each slot.
* 9. Sign message with each erased slot and check for fail.
* 10. Do steps 2-9, but instead of storing the key, generate it.
* 3. Calculate a hash of the message.
* 4. Sign message hash with each empty slot and check for fail.
* 5. Store pre-generated private key to each slot.
* 6. Read the public key from each slot.
* 7. Sign the message hash with each slot.
* 8. Verify the signature.
* 9. Erase each slot.
* 10. Sign message hash with each erased slot and check for fail.
* 11. Do steps 2-9, but instead of storing the key, generate it.
*
* @param h Handle for communication with TROPIC01
*/
Expand Down
52 changes: 26 additions & 26 deletions tests/functional/src/lt_test_rev_ecdsa_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,15 @@ void lt_test_rev_ecdsa_sign(lt_handle_t *h)
msg_to_sign_len);
LT_TEST_ASSERT(LT_OK, lt_random_bytes(h, msg_to_sign, msg_to_sign_len));

LT_LOG_INFO("Signing message with empty slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_to_sign, msg_to_sign_len, rs));
LT_LOG_INFO("Calculating hash of the message...");
LT_TEST_ASSERT(LT_OK, lt_sha256_init(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_start(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_update(h->l3.crypto_ctx, msg_to_sign, msg_to_sign_len));
LT_TEST_ASSERT(LT_OK, lt_sha256_finish(h->l3.crypto_ctx, msg_hash));
LT_TEST_ASSERT(LT_OK, lt_sha256_deinit(h->l3.crypto_ctx));

LT_LOG_INFO("Signing message hash with empty slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_hash, sizeof(msg_hash), rs));

LT_LOG_INFO("Storing private key pre-generated using P256 curve...");
LT_TEST_ASSERT(LT_OK, lt_ecc_key_store(h, i, TR01_CURVE_P256, priv_test_key));
Expand All @@ -132,24 +139,17 @@ void lt_test_rev_ecdsa_sign(lt_handle_t *h)
LT_TEST_ASSERT(LT_OK,
lt_ecc_key_read(h, i, read_pub_key, sizeof(read_pub_key), &curve, &origin));

LT_LOG_INFO("Signing message...");
LT_TEST_ASSERT(LT_OK, lt_ecc_ecdsa_sign(h, i, msg_to_sign, msg_to_sign_len, rs));

LT_LOG_INFO("Calculating hash of the message before verifying the signature...");
LT_TEST_ASSERT(LT_OK, lt_sha256_init(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_start(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_update(h->l3.crypto_ctx, msg_to_sign, msg_to_sign_len));
LT_TEST_ASSERT(LT_OK, lt_sha256_finish(h->l3.crypto_ctx, msg_hash));
LT_TEST_ASSERT(LT_OK, lt_sha256_deinit(h->l3.crypto_ctx));
LT_LOG_INFO("Signing message hash...");
LT_TEST_ASSERT(LT_OK, lt_ecc_ecdsa_sign(h, i, msg_hash, sizeof(msg_hash), rs));

LT_LOG_INFO("Verifying signature...");
LT_TEST_ASSERT(1, uECC_verify(read_pub_key, msg_hash, sizeof(msg_hash), rs, uECC_secp256r1()));

LT_LOG_INFO("Erasing the slot...");
LT_TEST_ASSERT(LT_OK, lt_ecc_key_erase(h, i));

LT_LOG_INFO("Signing message with erased slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_to_sign, msg_to_sign_len, rs));
LT_LOG_INFO("Signing message hash with erased slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_hash, sizeof(msg_hash), rs));
}
LT_LOG_LINE();

Expand All @@ -166,8 +166,15 @@ void lt_test_rev_ecdsa_sign(lt_handle_t *h)
msg_to_sign_len);
LT_TEST_ASSERT(LT_OK, lt_random_bytes(h, msg_to_sign, msg_to_sign_len));

LT_LOG_INFO("Signing message with empty slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_to_sign, msg_to_sign_len, rs));
LT_LOG_INFO("Calculating hash of the message...");
LT_TEST_ASSERT(LT_OK, lt_sha256_init(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_start(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_update(h->l3.crypto_ctx, msg_to_sign, msg_to_sign_len));
LT_TEST_ASSERT(LT_OK, lt_sha256_finish(h->l3.crypto_ctx, msg_hash));
LT_TEST_ASSERT(LT_OK, lt_sha256_deinit(h->l3.crypto_ctx));

LT_LOG_INFO("Signing message hash with empty slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_hash, sizeof(msg_hash), rs));

LT_LOG_INFO("Generating private key using P256 curve...");
LT_TEST_ASSERT(LT_OK, lt_ecc_key_generate(h, i, TR01_CURVE_P256));
Expand All @@ -176,24 +183,17 @@ void lt_test_rev_ecdsa_sign(lt_handle_t *h)
LT_TEST_ASSERT(LT_OK,
lt_ecc_key_read(h, i, read_pub_key, sizeof(read_pub_key), &curve, &origin));

LT_LOG_INFO("Signing message...");
LT_TEST_ASSERT(LT_OK, lt_ecc_ecdsa_sign(h, i, msg_to_sign, msg_to_sign_len, rs));

LT_LOG_INFO("Calculating hash of the message before verifying the signature...");
LT_TEST_ASSERT(LT_OK, lt_sha256_init(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_start(h->l3.crypto_ctx));
LT_TEST_ASSERT(LT_OK, lt_sha256_update(h->l3.crypto_ctx, msg_to_sign, msg_to_sign_len));
LT_TEST_ASSERT(LT_OK, lt_sha256_finish(h->l3.crypto_ctx, msg_hash));
LT_TEST_ASSERT(LT_OK, lt_sha256_deinit(h->l3.crypto_ctx));
LT_LOG_INFO("Signing message hash...");
LT_TEST_ASSERT(LT_OK, lt_ecc_ecdsa_sign(h, i, msg_hash, sizeof(msg_hash), rs));

LT_LOG_INFO("Verifying signature...");
LT_TEST_ASSERT(1, uECC_verify(read_pub_key, msg_hash, sizeof(msg_hash), rs, uECC_secp256r1()));

LT_LOG_INFO("Erasing the slot...");
LT_TEST_ASSERT(LT_OK, lt_ecc_key_erase(h, i));

LT_LOG_INFO("Signing message with erased slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_to_sign, msg_to_sign_len, rs));
LT_LOG_INFO("Signing message hash with erased slot (should fail)...");
LT_TEST_ASSERT(LT_L3_INVALID_KEY, lt_ecc_ecdsa_sign(h, i, msg_hash, sizeof(msg_hash), rs));
}
LT_LOG_LINE();

Expand Down