Implement Ledger-PKI
- Update src code to adapt to new API 'os_pki_verify' - Support both Ledger-PKI and legacy method
This commit is contained in:
76
src/ledger_pki.c
Normal file
76
src/ledger_pki.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include "apdu_constants.h"
|
||||||
|
#include "public_keys.h"
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
#include "os_pki.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define KEY_USAGE_STR(x) \
|
||||||
|
(x == CERTIFICATE_PUBLIC_KEY_USAGE_GENUINE_CHECK ? "GENUINE_CHECK" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_EXCHANGE_PAYLOAD ? "EXCHANGE_PAYLOAD" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_NFT_METADATA ? "NFT_METADATA" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_TRUSTED_NAME ? "TRUSTED_NAME" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_BACKUP_PROVIDER ? "BACKUP_PROVIDER" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_RECOVER_ORCHESTRATOR ? "RECOVER_ORCHESTRATOR" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_PLUGIN_METADATA ? "PLUGIN_METADATA" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META ? "COIN_META" \
|
||||||
|
: x == CERTIFICATE_PUBLIC_KEY_USAGE_SEED_ID_AUTH ? "SEED_ID_AUTH" \
|
||||||
|
: "Unknown")
|
||||||
|
|
||||||
|
int check_signature_with_pubkey(const char *tag,
|
||||||
|
uint8_t *buffer,
|
||||||
|
const uint8_t bufLen,
|
||||||
|
const uint8_t *PubKey,
|
||||||
|
const uint8_t keyLen,
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
const uint8_t keyUsageExp,
|
||||||
|
#endif
|
||||||
|
uint8_t *signature,
|
||||||
|
const uint8_t sigLen) {
|
||||||
|
UNUSED(tag);
|
||||||
|
cx_ecfp_public_key_t verif_key = {0};
|
||||||
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
uint8_t key_usage = 0;
|
||||||
|
size_t trusted_name_len = 0;
|
||||||
|
uint8_t trusted_name[CERTIFICATE_TRUSTED_NAME_MAXLEN] = {0};
|
||||||
|
cx_ecfp_384_public_key_t public_key = {0};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PRINTF(
|
||||||
|
"[%s] "
|
||||||
|
"=======================================================================================\n",
|
||||||
|
tag);
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
error = os_pki_get_info(&key_usage, trusted_name, &trusted_name_len, &public_key);
|
||||||
|
if ((error == 0) && (key_usage == keyUsageExp)) {
|
||||||
|
PRINTF("[%s] Certificate '%s' loaded for usage 0x%x (%s)\n",
|
||||||
|
tag,
|
||||||
|
trusted_name,
|
||||||
|
key_usage,
|
||||||
|
KEY_USAGE_STR(key_usage));
|
||||||
|
|
||||||
|
// Checking the signature with PKI
|
||||||
|
if (!os_pki_verify(buffer, bufLen, signature, sigLen)) {
|
||||||
|
PRINTF("%s: Invalid signature\n", tag);
|
||||||
|
#ifndef HAVE_BYPASS_SIGNATURES
|
||||||
|
error = APDU_RESPONSE_INVALID_DATA;
|
||||||
|
goto end;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
PRINTF("[%s] ********** No certificate loaded. Using legacy path **********\n", tag);
|
||||||
|
CX_CHECK(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, PubKey, keyLen, &verif_key));
|
||||||
|
if (!cx_ecdsa_verify_no_throw(&verif_key, buffer, bufLen, signature, sigLen)) {
|
||||||
|
PRINTF("%s: Invalid signature\n", tag);
|
||||||
|
#ifndef HAVE_BYPASS_SIGNATURES
|
||||||
|
error = APDU_RESPONSE_INVALID_DATA;
|
||||||
|
goto end;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error = CX_OK;
|
||||||
|
end:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
static const uint8_t LEDGER_SIGNATURE_PUBLIC_KEY[] = {
|
static const uint8_t LEDGER_SIGNATURE_PUBLIC_KEY[] = {
|
||||||
#if defined(HAVE_CAL_TEST_KEY)
|
#if defined(HAVE_CAL_TEST_KEY)
|
||||||
@@ -101,3 +102,14 @@ static const uint8_t LEDGER_NFT_SELECTOR_PUBLIC_KEY[] = {
|
|||||||
0x92, 0xc7, 0xc6, 0x48, 0x0d, 0x39, 0xce, 0xbb, 0xa3
|
0x92, 0xc7, 0xc6, 0x48, 0x0d, 0x39, 0xce, 0xbb, 0xa3
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int check_signature_with_pubkey(const char *tag,
|
||||||
|
uint8_t *buffer,
|
||||||
|
const uint8_t bufLen,
|
||||||
|
const uint8_t *PubKey,
|
||||||
|
const uint8_t keyLen,
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
const uint8_t keyUsageExp,
|
||||||
|
#endif
|
||||||
|
uint8_t *signature,
|
||||||
|
const uint8_t sigLen);
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
#include "hash_bytes.h"
|
#include "hash_bytes.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "public_keys.h"
|
#include "public_keys.h"
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
#include "os_pki.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define P1_FIRST_CHUNK 0x01
|
#define P1_FIRST_CHUNK 0x01
|
||||||
#define P1_FOLLOWING_CHUNK 0x00
|
#define P1_FOLLOWING_CHUNK 0x00
|
||||||
@@ -364,39 +367,36 @@ static bool handle_address(const s_tlv_data *data,
|
|||||||
*/
|
*/
|
||||||
static bool verify_signature(const s_sig_ctx *sig_ctx) {
|
static bool verify_signature(const s_sig_ctx *sig_ctx) {
|
||||||
uint8_t hash[INT256_LENGTH];
|
uint8_t hash[INT256_LENGTH];
|
||||||
cx_ecfp_public_key_t verif_key;
|
|
||||||
cx_err_t error = CX_INTERNAL_ERROR;
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
#ifdef HAVE_DOMAIN_NAME_TEST_KEY
|
||||||
|
e_key_id valid_key_id = KEY_ID_TEST;
|
||||||
|
#else
|
||||||
|
e_key_id valid_key_id = KEY_ID_PROD;
|
||||||
|
#endif
|
||||||
|
bool ret_code = false;
|
||||||
|
|
||||||
|
if (sig_ctx->key_id != valid_key_id) {
|
||||||
|
PRINTF("Error: Unknown metadata key ID %u\n", sig_ctx->key_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CX_CHECK(
|
CX_CHECK(
|
||||||
cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH));
|
cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH));
|
||||||
switch (sig_ctx->key_id) {
|
|
||||||
#ifdef HAVE_DOMAIN_NAME_TEST_KEY
|
CX_CHECK(check_signature_with_pubkey("Domain Name",
|
||||||
case KEY_ID_TEST:
|
hash,
|
||||||
#else
|
sizeof(hash),
|
||||||
case KEY_ID_PROD:
|
DOMAIN_NAME_PUB_KEY,
|
||||||
|
sizeof(DOMAIN_NAME_PUB_KEY),
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||||
#endif
|
#endif
|
||||||
CX_CHECK(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
(uint8_t *) (sig_ctx->input_sig),
|
||||||
DOMAIN_NAME_PUB_KEY,
|
sig_ctx->input_sig_size));
|
||||||
sizeof(DOMAIN_NAME_PUB_KEY),
|
|
||||||
&verif_key));
|
ret_code = true;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PRINTF("Error: Unknown metadata key ID %u\n", sig_ctx->key_id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!cx_ecdsa_verify_no_throw(&verif_key,
|
|
||||||
hash,
|
|
||||||
sizeof(hash),
|
|
||||||
sig_ctx->input_sig,
|
|
||||||
sig_ctx->input_sig_size)) {
|
|
||||||
PRINTF("Domain name signature verification failed!\n");
|
|
||||||
#ifndef HAVE_BYPASS_SIGNATURES
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
end:
|
end:
|
||||||
return false;
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
#include "os_io_seproxyhal.h"
|
#include "os_io_seproxyhal.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "manage_asset_info.h"
|
#include "manage_asset_info.h"
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
#include "os_pki.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void handleProvideErc20TokenInformation(uint8_t p1,
|
void handleProvideErc20TokenInformation(uint8_t p1,
|
||||||
uint8_t p2,
|
uint8_t p2,
|
||||||
@@ -20,22 +23,21 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
|||||||
uint8_t tickerLength;
|
uint8_t tickerLength;
|
||||||
uint64_t chain_id;
|
uint64_t chain_id;
|
||||||
uint8_t hash[INT256_LENGTH];
|
uint8_t hash[INT256_LENGTH];
|
||||||
cx_ecfp_public_key_t tokenKey;
|
|
||||||
|
|
||||||
tokenDefinition_t *token = &get_current_asset_info()->token;
|
tokenDefinition_t *token = &get_current_asset_info()->token;
|
||||||
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
|
||||||
PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);
|
PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);
|
||||||
|
|
||||||
if (dataLength < 1) {
|
if (dataLength < 1) {
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
tickerLength = workBuffer[offset++];
|
tickerLength = workBuffer[offset++];
|
||||||
dataLength--;
|
dataLength--;
|
||||||
if ((tickerLength + 1) > sizeof(token->ticker)) {
|
if ((tickerLength + 1) > sizeof(token->ticker)) {
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
if (dataLength < tickerLength + 20 + 4 + 4) {
|
if (dataLength < tickerLength + 20 + 4 + 4) {
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
|
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
|
||||||
memmove(token->ticker, workBuffer + offset, tickerLength);
|
memmove(token->ticker, workBuffer + offset, tickerLength);
|
||||||
@@ -53,21 +55,26 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
|||||||
chain_id = U4BE(workBuffer, offset);
|
chain_id = U4BE(workBuffer, offset);
|
||||||
if (!app_compatible_with_chain_id(&chain_id)) {
|
if (!app_compatible_with_chain_id(&chain_id)) {
|
||||||
UNSUPPORTED_CHAIN_ID_MSG(chain_id);
|
UNSUPPORTED_CHAIN_ID_MSG(chain_id);
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
offset += 4;
|
offset += 4;
|
||||||
dataLength -= 4;
|
dataLength -= 4;
|
||||||
|
|
||||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
error = check_signature_with_pubkey("ERC20 Token Info",
|
||||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
hash,
|
||||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
sizeof(hash),
|
||||||
&tokenKey));
|
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||||
if (!cx_ecdsa_verify_no_throw(&tokenKey, hash, 32, workBuffer + offset, dataLength)) {
|
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||||
#ifndef HAVE_BYPASS_SIGNATURES
|
#ifdef HAVE_LEDGER_PKI
|
||||||
PRINTF("Invalid token signature\n");
|
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||||
THROW(0x6A80);
|
|
||||||
#endif
|
#endif
|
||||||
|
(uint8_t *) (workBuffer + offset),
|
||||||
|
dataLength);
|
||||||
|
#ifndef HAVE_BYPASS_SIGNATURES
|
||||||
|
if (error != CX_OK) {
|
||||||
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
G_io_apdu_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
|
G_io_apdu_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
|
||||||
validate_current_asset_info();
|
validate_current_asset_info();
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "public_keys.h"
|
#include "public_keys.h"
|
||||||
#include "manage_asset_info.h"
|
#include "manage_asset_info.h"
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
#include "os_pki.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TYPE_SIZE 1
|
#define TYPE_SIZE 1
|
||||||
#define VERSION_SIZE 1
|
#define VERSION_SIZE 1
|
||||||
@@ -50,19 +53,29 @@ void handleProvideNFTInformation(uint8_t p1,
|
|||||||
UNUSED(tx);
|
UNUSED(tx);
|
||||||
UNUSED(flags);
|
UNUSED(flags);
|
||||||
uint8_t hash[INT256_LENGTH];
|
uint8_t hash[INT256_LENGTH];
|
||||||
cx_ecfp_public_key_t nftKey;
|
nftInfo_t *nft = NULL;
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t payloadSize = 0;
|
||||||
|
uint8_t collectionNameLength = 0;
|
||||||
|
uint64_t chain_id = 0;
|
||||||
|
uint8_t signatureLen = 0;
|
||||||
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
#ifdef HAVE_NFT_STAGING_KEY
|
||||||
|
uint8_t valid_keyId = STAGING_NFT_METADATA_KEY;
|
||||||
|
#else
|
||||||
|
uint8_t valid_keyId = PROD_NFT_METADATA_KEY;
|
||||||
|
#endif
|
||||||
|
|
||||||
PRINTF("In handle provide NFTInformation\n");
|
PRINTF("In handle provide NFTInformation\n");
|
||||||
|
|
||||||
if ((pluginType != ERC721) && (pluginType != ERC1155)) {
|
if ((pluginType != ERC721) && (pluginType != ERC1155)) {
|
||||||
PRINTF("NFT metadata provided without proper plugin loaded!\n");
|
PRINTF("NFT metadata provided without proper plugin loaded!\n");
|
||||||
THROW(0x6985);
|
THROW(0x6985);
|
||||||
}
|
}
|
||||||
nftInfo_t *nft = &get_current_asset_info()->nft;
|
nft = &get_current_asset_info()->nft;
|
||||||
|
|
||||||
PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);
|
PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);
|
||||||
|
|
||||||
size_t offset = 0;
|
|
||||||
|
|
||||||
if (dataLength <= HEADER_SIZE) {
|
if (dataLength <= HEADER_SIZE) {
|
||||||
PRINTF("Data too small for headers: expected at least %d, got %d\n",
|
PRINTF("Data too small for headers: expected at least %d, got %d\n",
|
||||||
HEADER_SIZE,
|
HEADER_SIZE,
|
||||||
@@ -70,34 +83,24 @@ void handleProvideNFTInformation(uint8_t p1,
|
|||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t type = workBuffer[offset];
|
if (workBuffer[offset] != TYPE_1) {
|
||||||
switch (type) {
|
PRINTF("Unsupported type %d\n", workBuffer[offset]);
|
||||||
case TYPE_1:
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PRINTF("Unsupported type %d\n", type);
|
|
||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
offset += TYPE_SIZE;
|
offset += TYPE_SIZE;
|
||||||
|
|
||||||
uint8_t version = workBuffer[offset];
|
if (workBuffer[offset] != VERSION_1) {
|
||||||
switch (version) {
|
PRINTF("Unsupported version %d\n", workBuffer[offset]);
|
||||||
case VERSION_1:
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PRINTF("Unsupported version %d\n", version);
|
|
||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
offset += VERSION_SIZE;
|
offset += VERSION_SIZE;
|
||||||
|
|
||||||
uint8_t collectionNameLength = workBuffer[offset];
|
collectionNameLength = workBuffer[offset];
|
||||||
offset += NAME_LENGTH_SIZE;
|
offset += NAME_LENGTH_SIZE;
|
||||||
|
|
||||||
// Size of the payload (everything except the signature)
|
// Size of the payload (everything except the signature)
|
||||||
size_t payloadSize = HEADER_SIZE + collectionNameLength + ADDRESS_LENGTH + CHAIN_ID_SIZE +
|
payloadSize = HEADER_SIZE + collectionNameLength + ADDRESS_LENGTH + CHAIN_ID_SIZE +
|
||||||
KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
||||||
if (dataLength < payloadSize) {
|
if (dataLength < payloadSize) {
|
||||||
PRINTF("Data too small for payload: expected at least %d, got %d\n",
|
PRINTF("Data too small for payload: expected at least %d, got %d\n",
|
||||||
payloadSize,
|
payloadSize,
|
||||||
@@ -124,7 +127,7 @@ void handleProvideNFTInformation(uint8_t p1,
|
|||||||
PRINTF("Address: %.*H\n", ADDRESS_LENGTH, workBuffer + offset);
|
PRINTF("Address: %.*H\n", ADDRESS_LENGTH, workBuffer + offset);
|
||||||
offset += ADDRESS_LENGTH;
|
offset += ADDRESS_LENGTH;
|
||||||
|
|
||||||
uint64_t chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
||||||
// this prints raw data, so to have a more meaningful print, display
|
// this prints raw data, so to have a more meaningful print, display
|
||||||
// the buffer before the endianness swap
|
// the buffer before the endianness swap
|
||||||
PRINTF("ChainID: %.*H\n", sizeof(chain_id), (workBuffer + offset));
|
PRINTF("ChainID: %.*H\n", sizeof(chain_id), (workBuffer + offset));
|
||||||
@@ -134,35 +137,18 @@ void handleProvideNFTInformation(uint8_t p1,
|
|||||||
}
|
}
|
||||||
offset += CHAIN_ID_SIZE;
|
offset += CHAIN_ID_SIZE;
|
||||||
|
|
||||||
uint8_t keyId = workBuffer[offset];
|
if (workBuffer[offset] != valid_keyId) {
|
||||||
const uint8_t *rawKey;
|
PRINTF("Unsupported KeyID %d\n", workBuffer[offset]);
|
||||||
uint8_t rawKeyLen;
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
|
|
||||||
PRINTF("KeyID: %d\n", keyId);
|
|
||||||
switch (keyId) {
|
|
||||||
#ifdef HAVE_NFT_STAGING_KEY
|
|
||||||
case STAGING_NFT_METADATA_KEY:
|
|
||||||
#endif
|
|
||||||
case PROD_NFT_METADATA_KEY:
|
|
||||||
rawKey = LEDGER_NFT_METADATA_PUBLIC_KEY;
|
|
||||||
rawKeyLen = sizeof(LEDGER_NFT_METADATA_PUBLIC_KEY);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PRINTF("KeyID %d not supported\n", keyId);
|
|
||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
PRINTF("RawKey: %.*H\n", rawKeyLen, rawKey);
|
|
||||||
offset += KEY_ID_SIZE;
|
offset += KEY_ID_SIZE;
|
||||||
|
|
||||||
uint8_t algorithmId = workBuffer[offset];
|
if (workBuffer[offset] != ALGORITHM_ID_1) {
|
||||||
PRINTF("Algorithm: %d\n", algorithmId);
|
PRINTF("Incorrect algorithmId %d\n", workBuffer[offset]);
|
||||||
|
|
||||||
if (algorithmId != ALGORITHM_ID_1) {
|
|
||||||
PRINTF("Incorrect algorithmId %d\n", algorithmId);
|
|
||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
offset += ALGORITHM_ID_SIZE;
|
offset += ALGORITHM_ID_SIZE;
|
||||||
|
|
||||||
PRINTF("hashing: %.*H\n", payloadSize, workBuffer);
|
PRINTF("hashing: %.*H\n", payloadSize, workBuffer);
|
||||||
cx_hash_sha256(workBuffer, payloadSize, hash, sizeof(hash));
|
cx_hash_sha256(workBuffer, payloadSize, hash, sizeof(hash));
|
||||||
|
|
||||||
@@ -171,7 +157,7 @@ void handleProvideNFTInformation(uint8_t p1,
|
|||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t signatureLen = workBuffer[offset];
|
signatureLen = workBuffer[offset];
|
||||||
PRINTF("Signature len: %d\n", signatureLen);
|
PRINTF("Signature len: %d\n", signatureLen);
|
||||||
if (signatureLen < MIN_DER_SIG_SIZE || signatureLen > MAX_DER_SIG_SIZE) {
|
if (signatureLen < MIN_DER_SIG_SIZE || signatureLen > MAX_DER_SIG_SIZE) {
|
||||||
PRINTF("SignatureLen too big or too small. Must be between %d and %d, got %d\n",
|
PRINTF("SignatureLen too big or too small. Must be between %d and %d, got %d\n",
|
||||||
@@ -187,17 +173,21 @@ void handleProvideNFTInformation(uint8_t p1,
|
|||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, rawKey, rawKeyLen, &nftKey));
|
error = check_signature_with_pubkey("NFT Info",
|
||||||
if (!cx_ecdsa_verify_no_throw(&nftKey,
|
hash,
|
||||||
hash,
|
sizeof(hash),
|
||||||
sizeof(hash),
|
LEDGER_NFT_METADATA_PUBLIC_KEY,
|
||||||
(uint8_t *) workBuffer + offset,
|
sizeof(LEDGER_NFT_METADATA_PUBLIC_KEY),
|
||||||
signatureLen)) {
|
#ifdef HAVE_LEDGER_PKI
|
||||||
#ifndef HAVE_BYPASS_SIGNATURES
|
CERTIFICATE_PUBLIC_KEY_USAGE_NFT_METADATA,
|
||||||
PRINTF("Invalid NFT signature\n");
|
|
||||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
|
||||||
#endif
|
#endif
|
||||||
|
(uint8_t *) (workBuffer + offset),
|
||||||
|
signatureLen);
|
||||||
|
#ifndef HAVE_BYPASS_SIGNATURES
|
||||||
|
if (error != CX_OK) {
|
||||||
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
G_io_apdu_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
|
G_io_apdu_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
|
||||||
validate_current_asset_info();
|
validate_current_asset_info();
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include "plugin_utils.h"
|
#include "plugin_utils.h"
|
||||||
#include "common_ui.h"
|
#include "common_ui.h"
|
||||||
#include "os_io_seproxyhal.h"
|
#include "os_io_seproxyhal.h"
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
#include "os_pki.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void handleSetExternalPlugin(uint8_t p1,
|
void handleSetExternalPlugin(uint8_t p1,
|
||||||
uint8_t p2,
|
uint8_t p2,
|
||||||
@@ -18,41 +21,43 @@ void handleSetExternalPlugin(uint8_t p1,
|
|||||||
UNUSED(flags);
|
UNUSED(flags);
|
||||||
PRINTF("Handling set Plugin\n");
|
PRINTF("Handling set Plugin\n");
|
||||||
uint8_t hash[INT256_LENGTH];
|
uint8_t hash[INT256_LENGTH];
|
||||||
cx_ecfp_public_key_t tokenKey;
|
|
||||||
uint8_t pluginNameLength = *workBuffer;
|
uint8_t pluginNameLength = *workBuffer;
|
||||||
|
uint32_t params[2];
|
||||||
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
|
||||||
PRINTF("plugin Name Length: %d\n", pluginNameLength);
|
PRINTF("plugin Name Length: %d\n", pluginNameLength);
|
||||||
const size_t payload_size = 1 + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE;
|
const size_t payload_size = 1 + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE;
|
||||||
|
|
||||||
if (dataLength <= payload_size) {
|
if (dataLength <= payload_size) {
|
||||||
PRINTF("data too small: expected at least %d got %d\n", payload_size, dataLength);
|
PRINTF("data too small: expected at least %d got %d\n", payload_size, dataLength);
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginNameLength + 1 > sizeof(dataContext.tokenContext.pluginName)) {
|
if (pluginNameLength + 1 > sizeof(dataContext.tokenContext.pluginName)) {
|
||||||
PRINTF("name length too big: expected max %d, got %d\n",
|
PRINTF("name length too big: expected max %d, got %d\n",
|
||||||
sizeof(dataContext.tokenContext.pluginName),
|
sizeof(dataContext.tokenContext.pluginName),
|
||||||
pluginNameLength + 1);
|
pluginNameLength + 1);
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check Ledger's signature over the payload
|
// check Ledger's signature over the payload
|
||||||
cx_hash_sha256(workBuffer, payload_size, hash, sizeof(hash));
|
cx_hash_sha256(workBuffer, payload_size, hash, sizeof(hash));
|
||||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
|
||||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
error = check_signature_with_pubkey("External Plugin",
|
||||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
hash,
|
||||||
&tokenKey));
|
sizeof(hash),
|
||||||
if (!cx_ecdsa_verify_no_throw(&tokenKey,
|
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||||
hash,
|
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||||
sizeof(hash),
|
#ifdef HAVE_LEDGER_PKI
|
||||||
workBuffer + payload_size,
|
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||||
dataLength - payload_size)) {
|
|
||||||
#ifndef HAVE_BYPASS_SIGNATURES
|
|
||||||
PRINTF("Invalid plugin signature %.*H\n",
|
|
||||||
dataLength - payload_size,
|
|
||||||
workBuffer + payload_size);
|
|
||||||
THROW(0x6A80);
|
|
||||||
#endif
|
#endif
|
||||||
|
(uint8_t *) (workBuffer + payload_size),
|
||||||
|
dataLength - payload_size);
|
||||||
|
#ifndef HAVE_BYPASS_SIGNATURES
|
||||||
|
if (error != CX_OK) {
|
||||||
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// move on to the rest of the payload parsing
|
// move on to the rest of the payload parsing
|
||||||
workBuffer++;
|
workBuffer++;
|
||||||
@@ -63,7 +68,6 @@ void handleSetExternalPlugin(uint8_t p1,
|
|||||||
PRINTF("Check external plugin %s\n", dataContext.tokenContext.pluginName);
|
PRINTF("Check external plugin %s\n", dataContext.tokenContext.pluginName);
|
||||||
|
|
||||||
// Check if the plugin is present on the device
|
// Check if the plugin is present on the device
|
||||||
uint32_t params[2];
|
|
||||||
params[0] = (uint32_t) dataContext.tokenContext.pluginName;
|
params[0] = (uint32_t) dataContext.tokenContext.pluginName;
|
||||||
params[1] = ETH_PLUGIN_CHECK_PRESENCE;
|
params[1] = ETH_PLUGIN_CHECK_PRESENCE;
|
||||||
BEGIN_TRY {
|
BEGIN_TRY {
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#include "os_io_seproxyhal.h"
|
#include "os_io_seproxyhal.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "public_keys.h"
|
#include "public_keys.h"
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
#include "os_pki.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Supported internal plugins
|
// Supported internal plugins
|
||||||
#define ERC721_STR "ERC721"
|
#define ERC721_STR "ERC721"
|
||||||
@@ -82,53 +85,51 @@ void handleSetPlugin(uint8_t p1,
|
|||||||
UNUSED(flags);
|
UNUSED(flags);
|
||||||
PRINTF("Handling set Plugin\n");
|
PRINTF("Handling set Plugin\n");
|
||||||
uint8_t hash[INT256_LENGTH] = {0};
|
uint8_t hash[INT256_LENGTH] = {0};
|
||||||
cx_ecfp_public_key_t pluginKey = {0};
|
|
||||||
tokenContext_t *tokenContext = &dataContext.tokenContext;
|
tokenContext_t *tokenContext = &dataContext.tokenContext;
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
uint8_t pluginNameLength = 0;
|
||||||
|
size_t payloadSize = 0;
|
||||||
|
uint64_t chain_id = 0;
|
||||||
|
uint8_t signatureLen = 0;
|
||||||
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
#ifdef HAVE_NFT_STAGING_KEY
|
||||||
|
enum KeyId valid_keyId = TEST_PLUGIN_KEY;
|
||||||
|
#else
|
||||||
|
enum KeyId valid_keyId = PROD_PLUGIN_KEY;
|
||||||
|
#endif
|
||||||
|
enum KeyId keyId;
|
||||||
|
uint32_t params[2];
|
||||||
|
|
||||||
if (dataLength <= HEADER_SIZE) {
|
if (dataLength <= HEADER_SIZE) {
|
||||||
PRINTF("Data too small for headers: expected at least %d, got %d\n",
|
PRINTF("Data too small for headers: expected at least %d, got %d\n",
|
||||||
HEADER_SIZE,
|
HEADER_SIZE,
|
||||||
dataLength);
|
dataLength);
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Type type = workBuffer[offset];
|
if (workBuffer[offset] != ETH_PLUGIN) {
|
||||||
PRINTF("Type: %d\n", type);
|
PRINTF("Unsupported type %d\n", workBuffer[offset]);
|
||||||
switch (type) {
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
case ETH_PLUGIN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PRINTF("Unsupported type %d\n", type);
|
|
||||||
THROW(0x6a80);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
offset += TYPE_SIZE;
|
offset += TYPE_SIZE;
|
||||||
|
|
||||||
uint8_t version = workBuffer[offset];
|
if (workBuffer[offset] != VERSION_1) {
|
||||||
PRINTF("version: %d\n", version);
|
PRINTF("Unsupported version %d\n", workBuffer[offset]);
|
||||||
switch (version) {
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
case VERSION_1:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PRINTF("Unsupported version %d\n", version);
|
|
||||||
THROW(0x6a80);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
offset += VERSION_SIZE;
|
offset += VERSION_SIZE;
|
||||||
|
|
||||||
uint8_t pluginNameLength = workBuffer[offset];
|
pluginNameLength = workBuffer[offset];
|
||||||
offset += PLUGIN_NAME_LENGTH_SIZE;
|
offset += PLUGIN_NAME_LENGTH_SIZE;
|
||||||
|
|
||||||
// Size of the payload (everything except the signature)
|
// Size of the payload (everything except the signature)
|
||||||
size_t payloadSize = HEADER_SIZE + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE +
|
payloadSize = HEADER_SIZE + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE + CHAIN_ID_SIZE +
|
||||||
CHAIN_ID_SIZE + KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
||||||
if (dataLength < payloadSize) {
|
if (dataLength < payloadSize) {
|
||||||
PRINTF("Data too small for payload: expected at least %d, got %d\n",
|
PRINTF("Data too small for payload: expected at least %d, got %d\n",
|
||||||
payloadSize,
|
payloadSize,
|
||||||
dataLength);
|
dataLength);
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `+ 1` because we want to add a null terminating character.
|
// `+ 1` because we want to add a null terminating character.
|
||||||
@@ -136,7 +137,7 @@ void handleSetPlugin(uint8_t p1,
|
|||||||
PRINTF("plugin name too big: expected max %d, got %d\n",
|
PRINTF("plugin name too big: expected max %d, got %d\n",
|
||||||
sizeof(dataContext.tokenContext.pluginName),
|
sizeof(dataContext.tokenContext.pluginName),
|
||||||
pluginNameLength + 1);
|
pluginNameLength + 1);
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe because we've checked the size before.
|
// Safe because we've checked the size before.
|
||||||
@@ -155,7 +156,7 @@ void handleSetPlugin(uint8_t p1,
|
|||||||
PRINTF("Selector: %.*H\n", SELECTOR_SIZE, tokenContext->methodSelector);
|
PRINTF("Selector: %.*H\n", SELECTOR_SIZE, tokenContext->methodSelector);
|
||||||
offset += SELECTOR_SIZE;
|
offset += SELECTOR_SIZE;
|
||||||
|
|
||||||
uint64_t chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
||||||
// this prints raw data, so to have a more meaningful print, display
|
// this prints raw data, so to have a more meaningful print, display
|
||||||
// the buffer before the endianness swap
|
// the buffer before the endianness swap
|
||||||
PRINTF("ChainID: %.*H\n", sizeof(chain_id), (workBuffer + offset));
|
PRINTF("ChainID: %.*H\n", sizeof(chain_id), (workBuffer + offset));
|
||||||
@@ -165,105 +166,86 @@ void handleSetPlugin(uint8_t p1,
|
|||||||
}
|
}
|
||||||
offset += CHAIN_ID_SIZE;
|
offset += CHAIN_ID_SIZE;
|
||||||
|
|
||||||
enum KeyId keyId = workBuffer[offset];
|
keyId = workBuffer[offset];
|
||||||
uint8_t const *rawKey;
|
if (keyId != valid_keyId) {
|
||||||
uint8_t rawKeyLen;
|
PRINTF("Unsupported KeyID %d\n", keyId);
|
||||||
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
PRINTF("KeyID: %d\n", keyId);
|
|
||||||
switch (keyId) {
|
|
||||||
#ifdef HAVE_NFT_STAGING_KEY
|
|
||||||
case TEST_PLUGIN_KEY:
|
|
||||||
#endif
|
|
||||||
case PROD_PLUGIN_KEY:
|
|
||||||
rawKey = LEDGER_NFT_SELECTOR_PUBLIC_KEY;
|
|
||||||
rawKeyLen = sizeof(LEDGER_NFT_SELECTOR_PUBLIC_KEY);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PRINTF("KeyID %d not supported\n", keyId);
|
|
||||||
THROW(0x6A80);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINTF("RawKey: %.*H\n", rawKeyLen, rawKey);
|
|
||||||
offset += KEY_ID_SIZE;
|
offset += KEY_ID_SIZE;
|
||||||
|
|
||||||
uint8_t algorithmId = workBuffer[offset];
|
if (workBuffer[offset] != ECC_SECG_P256K1__ECDSA_SHA_256) {
|
||||||
PRINTF("Algorithm: %d\n", algorithmId);
|
PRINTF("Incorrect algorithmId %d\n", workBuffer[offset]);
|
||||||
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
if (algorithmId != ECC_SECG_P256K1__ECDSA_SHA_256) {
|
|
||||||
PRINTF("Incorrect algorithmId %d\n", algorithmId);
|
|
||||||
THROW(0x6a80);
|
|
||||||
}
|
}
|
||||||
offset += ALGORITHM_ID_SIZE;
|
offset += ALGORITHM_ID_SIZE;
|
||||||
|
|
||||||
PRINTF("hashing: %.*H\n", payloadSize, workBuffer);
|
PRINTF("hashing: %.*H\n", payloadSize, workBuffer);
|
||||||
cx_hash_sha256(workBuffer, payloadSize, hash, sizeof(hash));
|
cx_hash_sha256(workBuffer, payloadSize, hash, sizeof(hash));
|
||||||
|
|
||||||
if (dataLength < payloadSize + SIGNATURE_LENGTH_SIZE) {
|
if (dataLength < payloadSize + SIGNATURE_LENGTH_SIZE) {
|
||||||
PRINTF("Data too short to hold signature length\n");
|
PRINTF("Data too short to hold signature length\n");
|
||||||
THROW(0x6a80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t signatureLen = workBuffer[offset];
|
signatureLen = workBuffer[offset];
|
||||||
PRINTF("Signature len: %d\n", signatureLen);
|
PRINTF("Signature len: %d\n", signatureLen);
|
||||||
if (signatureLen < MIN_DER_SIG_SIZE || signatureLen > MAX_DER_SIG_SIZE) {
|
if (signatureLen < MIN_DER_SIG_SIZE || signatureLen > MAX_DER_SIG_SIZE) {
|
||||||
PRINTF("SignatureLen too big or too small. Must be between %d and %d, got %d\n",
|
PRINTF("SignatureLen too big or too small. Must be between %d and %d, got %d\n",
|
||||||
MIN_DER_SIG_SIZE,
|
MIN_DER_SIG_SIZE,
|
||||||
MAX_DER_SIG_SIZE,
|
MAX_DER_SIG_SIZE,
|
||||||
signatureLen);
|
signatureLen);
|
||||||
THROW(0x6a80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
offset += SIGNATURE_LENGTH_SIZE;
|
offset += SIGNATURE_LENGTH_SIZE;
|
||||||
|
|
||||||
if (dataLength < payloadSize + SIGNATURE_LENGTH_SIZE + signatureLen) {
|
if (dataLength < payloadSize + SIGNATURE_LENGTH_SIZE + signatureLen) {
|
||||||
PRINTF("Signature could not fit in data\n");
|
PRINTF("Signature could not fit in data\n");
|
||||||
THROW(0x6a80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, rawKey, rawKeyLen, &pluginKey));
|
error = check_signature_with_pubkey("Set Plugin",
|
||||||
if (!cx_ecdsa_verify_no_throw(&pluginKey,
|
hash,
|
||||||
hash,
|
sizeof(hash),
|
||||||
sizeof(hash),
|
LEDGER_NFT_SELECTOR_PUBLIC_KEY,
|
||||||
(unsigned char *) (workBuffer + offset),
|
sizeof(LEDGER_NFT_SELECTOR_PUBLIC_KEY),
|
||||||
signatureLen)) {
|
#ifdef HAVE_LEDGER_PKI
|
||||||
#ifndef HAVE_BYPASS_SIGNATURES
|
CERTIFICATE_PUBLIC_KEY_USAGE_PLUGIN_METADATA,
|
||||||
PRINTF("Invalid NFT signature\n");
|
|
||||||
THROW(0x6A80);
|
|
||||||
#endif
|
#endif
|
||||||
|
(uint8_t *) (workBuffer + offset),
|
||||||
|
signatureLen);
|
||||||
|
#ifndef HAVE_BYPASS_SIGNATURES
|
||||||
|
if (error != CX_OK) {
|
||||||
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pluginType = getPluginType(tokenContext->pluginName, pluginNameLength);
|
pluginType = getPluginType(tokenContext->pluginName, pluginNameLength);
|
||||||
if (keyId == PROD_PLUGIN_KEY) {
|
if (keyId == PROD_PLUGIN_KEY) {
|
||||||
if (pluginType != ERC721 && pluginType != ERC1155) {
|
if (pluginType != ERC721 && pluginType != ERC1155) {
|
||||||
PRINTF("AWS key must only be used to set NFT internal plugins\n");
|
PRINTF("AWS key must only be used to set NFT internal plugins\n");
|
||||||
THROW(0x6A80);
|
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pluginType) {
|
if (pluginType == EXTERNAL) {
|
||||||
case EXTERNAL: {
|
PRINTF("Check external plugin %s\n", tokenContext->pluginName);
|
||||||
PRINTF("Check external plugin %s\n", tokenContext->pluginName);
|
|
||||||
|
|
||||||
// Check if the plugin is present on the device
|
// Check if the plugin is present on the device
|
||||||
uint32_t params[2];
|
params[0] = (uint32_t) tokenContext->pluginName;
|
||||||
params[0] = (uint32_t) tokenContext->pluginName;
|
params[1] = ETH_PLUGIN_CHECK_PRESENCE;
|
||||||
params[1] = ETH_PLUGIN_CHECK_PRESENCE;
|
BEGIN_TRY {
|
||||||
BEGIN_TRY {
|
TRY {
|
||||||
TRY {
|
os_lib_call(params);
|
||||||
os_lib_call(params);
|
}
|
||||||
}
|
CATCH_OTHER(e) {
|
||||||
CATCH_OTHER(e) {
|
PRINTF("%s external plugin is not present\n", tokenContext->pluginName);
|
||||||
PRINTF("%s external plugin is not present\n", tokenContext->pluginName);
|
memset(tokenContext->pluginName, 0, sizeof(tokenContext->pluginName));
|
||||||
memset(tokenContext->pluginName, 0, sizeof(tokenContext->pluginName));
|
THROW(0x6984);
|
||||||
THROW(0x6984);
|
}
|
||||||
}
|
FINALLY {
|
||||||
FINALLY {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
END_TRY;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
END_TRY;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G_io_apdu_buffer[(*tx)++] = 0x90;
|
G_io_apdu_buffer[(*tx)++] = 0x90;
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "ui_logic.h"
|
#include "ui_logic.h"
|
||||||
#include "filtering.h"
|
#include "filtering.h"
|
||||||
|
#ifdef HAVE_LEDGER_PKI
|
||||||
|
#include "os_pki.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FILT_MAGIC_MESSAGE_INFO 183
|
#define FILT_MAGIC_MESSAGE_INFO 183
|
||||||
#define FILT_MAGIC_AMOUNT_JOIN_TOKEN 11
|
#define FILT_MAGIC_AMOUNT_JOIN_TOKEN 11
|
||||||
@@ -95,26 +98,26 @@ static bool sig_verif_start(cx_sha256_t *hash_ctx, uint8_t magic) {
|
|||||||
*/
|
*/
|
||||||
static bool sig_verif_end(cx_sha256_t *hash_ctx, const uint8_t *sig, uint8_t sig_length) {
|
static bool sig_verif_end(cx_sha256_t *hash_ctx, const uint8_t *sig, uint8_t sig_length) {
|
||||||
uint8_t hash[INT256_LENGTH];
|
uint8_t hash[INT256_LENGTH];
|
||||||
cx_ecfp_public_key_t verifying_key;
|
|
||||||
cx_err_t error = CX_INTERNAL_ERROR;
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
bool ret_code = false;
|
||||||
|
|
||||||
// Finalize hash
|
// Finalize hash
|
||||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH));
|
CX_CHECK(cx_hash_no_throw((cx_hash_t *) hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH));
|
||||||
|
|
||||||
CX_CHECK(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
CX_CHECK(check_signature_with_pubkey("EIP712 Filtering",
|
||||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
hash,
|
||||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
sizeof(hash),
|
||||||
&verifying_key));
|
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||||
if (!cx_ecdsa_verify_no_throw(&verifying_key, hash, sizeof(hash), sig, sig_length)) {
|
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||||
#ifndef HAVE_BYPASS_SIGNATURES
|
#ifdef HAVE_LEDGER_PKI
|
||||||
PRINTF("Invalid EIP-712 filtering signature\n");
|
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
|
||||||
return false;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
(uint8_t *) (sig),
|
||||||
return true;
|
sig_length));
|
||||||
|
|
||||||
|
ret_code = true;
|
||||||
end:
|
end:
|
||||||
return false;
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user