swap_handle_check_address()
ledger-secure-sdk/lib_standard_app/swap_entrypoints.h
/* This handle is called when the Exchange application wants to ensure that a
* given address belongs to the device.
*
* If the address does belong to the device, result is set to 1. Otherwise it
* is set to 0.
*/
void swap_handle_check_address(check_address_parameters_t *params);
ledger-secure-sdk/lib_standard_app/swap_lib_calls.h
typedef struct check_address_parameters_s {
// INPUTS //
// Additional data when dealing with tokens
// Content is coin application specific
uint8_t *coin_configuration;
uint8_t coin_configuration_length;
// serialized path, segwit, version prefix, hash used, dictionary etc.
// fields and serialization format are coin application specific
uint8_t *address_parameters;
uint8_t address_parameters_length;
// The address to check
char *address_to_check;
// Extra content that may be relevant depending on context: memo, calldata, ...
// Content is coin application specific
char *extra_id_to_check;
// OUTPUT //
// Set to 1 if the address belongs to the device. 0 otherwise.
int result;
} check_address_parameters_t;
Example of handle implementation in Boilerplate
app-boilerplate/src/swap/handle_check_address.c
#ifdef HAVE_SWAP
#include "swap.h"
#include "buffer.h"
#include "bip32.h"
#include "crypto_helpers.h"
#include "cx.h"
#include "os.h"
#include "types.h"
#include "format.h"
#include "address.h"
#include "tx_types.h"
#include <string.h>
/* Check that the address used to receive funds is owned by the device
* check_address_parameters_t is defined in C SDK as:
* struct {
* // IN
* uint8_t *coin_configuration;
* uint8_t coin_configuration_length;
* // serialized path, segwit, version prefix, hash used, dictionary etc.
* // fields and serialization format depends on specific coin app
* uint8_t *address_parameters;
* uint8_t address_parameters_length;
* char *address_to_check;
* char *extra_id_to_check;
* // OUT
* int result;
* } check_address_parameters_t;
*/
void swap_handle_check_address(check_address_parameters_t *params) {
PRINTF("Inside swap_handle_check_address\n");
params->result = 0;
if (params->address_parameters == NULL) {
PRINTF("derivation path expected\n");
return;
}
PRINTF("address_parameters %.*H\n",
params->address_parameters_length,
params->address_parameters);
if (params->address_to_check == NULL) {
PRINTF("Address to check expected\n");
return;
}
PRINTF("Address to check %s\n", params->address_to_check);
if (strlen(params->address_to_check) != (ADDRESS_LEN * 2)) {
PRINTF("Address to check expected length %d, not %d\n",
ADDRESS_LEN * 2,
strlen(params->address_to_check));
return;
}
buffer_t buf = {.ptr = params->address_parameters,
.size = params->address_parameters_length,
.offset = 0};
uint8_t bip32_path_len;
uint32_t bip32_path[MAX_BIP32_PATH];
pubkey_ctx_t pk_info = {0};
buffer_read_u8(&buf, &bip32_path_len);
buffer_read_bip32_path(&buf, bip32_path, (size_t) bip32_path_len);
cx_err_t ret = bip32_derive_get_pubkey_256(CX_CURVE_256K1,
bip32_path,
bip32_path_len,
pk_info.raw_public_key,
pk_info.chain_code,
CX_SHA512);
if (ret != CX_OK) {
PRINTF("Failed to derive public key\n");
return;
}
uint8_t address[ADDRESS_LEN] = {0};
address_from_pubkey(pk_info.raw_public_key, address, sizeof(address));
char derived_address[41];
memset(derived_address, 0, sizeof(derived_address));
format_hex(address, sizeof(address), derived_address, sizeof(derived_address));
PRINTF("Derived address %s\n", derived_address);
PRINTF("Checked address %s\n", params->address_to_check);
if (strncmp(derived_address, params->address_to_check, sizeof(derived_address)) != 0) {
PRINTF("Addresses do not match\n");
} else {
PRINTF("Addresses match\n");
params->result = 1;
}
}
#endif // HAVE_SWAP