Skip to content

Commit

Permalink
Add a field for signature format selection in CHECK_TRANSACTION_SIGNA…
Browse files Browse the repository at this point in the history
…TURE command on NG flows
  • Loading branch information
fbeutin-ledger committed Oct 13, 2023
1 parent a1295a7 commit fb6b3b5
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 14 deletions.
49 changes: 38 additions & 11 deletions src/check_tx_signature.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,60 @@ int check_tx_signature(const command_t *cmd) {
// signature
uint8_t der_sig[DER_HEADER_SIZE + MAX_DER_INT_SIZE(R_S_INT_SIZE) * 2];
buf_t signature;
bool signature_is_in_R_S_format;
uint16_t offset = 0;

if (cmd->subcommand == SWAP || cmd->subcommand == FUND) {
if (cmd->subcommand == SWAP) {
signature_is_in_R_S_format = false;
} else if (cmd->subcommand == FUND) {
signature_is_in_R_S_format = false;
} else if (cmd->subcommand == SELL) {
signature_is_in_R_S_format = true;
} else {
uint8_t sig_format;
if (!pop_uint8_from_buffer(cmd->data.bytes, cmd->data.size, &sig_format, &offset)) {
PRINTF("Failed to read signature format selector\n");
return reply_error(INCORRECT_COMMAND_DATA);
}
if (sig_format == DER_FORMAT_SIGNATURE) {
signature_is_in_R_S_format = false;
} else if (sig_format == R_S_FORMAT_SIGNATURE) {
signature_is_in_R_S_format = true;
} else {
PRINTF("Error: Incorrect signature format selector %d\n", sig_format);
return reply_error(INCORRECT_COMMAND_DATA);
}
}

buf_t remaining_input;
remaining_input.size = cmd->data.size - offset;
remaining_input.bytes = cmd->data.bytes + offset;
if (!signature_is_in_R_S_format) {
// We received the signature in DER format, just perform some sanity checks
if (cmd->data.size < MIN_DER_SIGNATURE_LENGTH ||
cmd->data.size > MAX_DER_SIGNATURE_LENGTH) {
if (remaining_input.size < MIN_DER_SIGNATURE_LENGTH ||
remaining_input.size > MAX_DER_SIGNATURE_LENGTH) {
PRINTF("Error: Input buffer length don't correspond to DER length\n");
return reply_error(INCORRECT_COMMAND_DATA);
}

uint16_t payload_size = cmd->data.bytes[DER_OFFSET_LENGTH];
if (payload_size + DER_HEADER_SIZE != cmd->data.size) {
uint16_t payload_size = remaining_input.bytes[DER_OFFSET_LENGTH];
if (payload_size + DER_HEADER_SIZE != remaining_input.size) {
PRINTF("DER signature header advertizes %d bytes, we received %d\n",
payload_size,
cmd->data.size);
remaining_input.size);
return reply_error(INCORRECT_COMMAND_DATA);
}
signature.size = cmd->data.size;
signature.bytes = cmd->data.bytes;
signature.size = remaining_input.size;
signature.bytes = remaining_input.bytes;
} else {
// We received the signature in (R,S) format, perform some sanity checks then encode in DER
if (cmd->data.size != R_S_INT_SIZE * 2) {
if (remaining_input.size != R_S_INT_SIZE * 2) {
PRINTF("Error: Input buffer length don't correspond to (R, S) length\n");
return reply_error(INCORRECT_COMMAND_DATA);
}

uint8_t *r = cmd->data.bytes;
uint8_t *s = cmd->data.bytes + R_S_INT_SIZE;
uint8_t *r = remaining_input.bytes;
uint8_t *s = remaining_input.bytes + R_S_INT_SIZE;
size_t der_r_len = asn1_get_encoded_integer_size(r, R_S_INT_SIZE);
size_t der_s_len = asn1_get_encoded_integer_size(s, R_S_INT_SIZE);
size_t size = der_r_len + der_s_len + DER_HEADER_SIZE;
Expand Down
3 changes: 3 additions & 0 deletions src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#define ENCODING_BYTES_ARRAY 0x00
#define ENCODING_BASE_64_URL 0x01

#define DER_FORMAT_SIGNATURE 0x00
#define R_S_FORMAT_SIGNATURE 0x01

#define TICKER_MIN_SIZE_B 2
#define TICKER_MAX_SIZE_B 9
#define APPNAME_MIN_SIZE_B 3
Expand Down
12 changes: 9 additions & 3 deletions test/python/apps/exchange_transaction_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def encode_payload(self, raw_transaction: bytes, url_encode: bool) -> bytes:
else:
return raw_transaction

def encode_signature(self, signature_to_encode: bytes) -> bytes:
if self.signature_encoding == SignatureEncoding.PLAIN_R_S:
def encode_signature(self, signature_to_encode: bytes, r_s_encode: bool) -> bytes:
if r_s_encode == True:
r, s = decode_dss_signature(signature_to_encode)
signature_to_encode = r.to_bytes(32, "big") + s.to_bytes(32, "big")
return signature_to_encode
Expand Down Expand Up @@ -170,7 +170,13 @@ def encode_transaction_signature(subcommand: SubCommand, signer: SigningAuthorit
subcommand_specs = SUBCOMMAND_TO_SPECS[subcommand]
formated_transaction = subcommand_specs.format_transaction(tx)
signed_transaction = signer.sign(formated_transaction)
return subcommand_specs.encode_signature(signed_transaction)
r_s_encode = True if (subcommand_specs.signature_encoding == SignatureEncoding.PLAIN_R_S) else False
encoded_signature = subcommand_specs.encode_signature(signed_transaction, r_s_encode)

if subcommand == SubCommand.SWAP_NG or subcommand == SubCommand.SELL_NG or subcommand == SubCommand.FUND_NG:
rs_encode = int.to_bytes(1 if r_s_encode == True else False, 1, byteorder='big')
encoded_signature = rs_encode + encoded_signature
return encoded_signature

def craft_transaction(subcommand: SubCommand, transaction: bytes, fees: int) -> bytes:
subcommand_specs = SUBCOMMAND_TO_SPECS[subcommand]
Expand Down

0 comments on commit fb6b3b5

Please sign in to comment.