Skip to content
Merged
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
537 changes: 537 additions & 0 deletions docs/Generalized-Tendermint-Signing.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
* [Supported Coins](Coins.md)
* [Host Communications](Host.md)
* [Release Process](Release.md)
* [Generalized Cosmos and Tendermint Signing](Generalized-Tendermint-Signing.md)
294 changes: 294 additions & 0 deletions docs/security/7.15.0-rc17-hardening.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions include/keepkey/board/font.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#ifndef FONT_H
#define FONT_H

#include <stddef.h>
#include <stdint.h>

/* Data pertaining to the image of a character */
Expand Down Expand Up @@ -53,5 +54,9 @@ uint32_t font_width(const Font* font);

uint32_t calc_str_width(const Font* font, const char* str);
uint32_t calc_str_line(const Font* font, const char* str, uint16_t line_width);
uint32_t calc_str_line_n(const Font* font, const char* str, size_t str_len,
uint16_t line_width);
size_t calc_str_page(const Font* font, const char* str, size_t str_len,
uint16_t line_width, uint32_t max_lines);

#endif
5 changes: 2 additions & 3 deletions include/keepkey/board/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ void dec64_to_str(uint64_t dec64_val, char* str);

bool is_valid_ascii(const uint8_t* data, uint32_t size);

int base_to_precision(uint8_t* dest, const uint8_t* value,
const uint8_t dest_len, const uint8_t value_len,
const uint8_t precision);
int base_to_precision(uint8_t* dest, const uint8_t* value, size_t dest_len,
size_t value_len, uint8_t precision);

#endif
9 changes: 9 additions & 0 deletions include/keepkey/firmware/app_confirm.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>

#define CONFIRM_SIGN_IDENTITY_TITLE 32
#define CONFIRM_SIGN_IDENTITY_BODY 416
Expand All @@ -46,6 +47,14 @@ bool confirm_load_device(bool is_node);
bool confirm_address(const char* desc, const char* address);
bool confirm_xpub(const char* node_str, const char* xpub);
bool confirm_sign_identity(const IdentityType* identity, const char* challenge);
/**
* Review every byte of a length-delimited payload. Printable ASCII is paged as
* text; any payload containing a control/non-ASCII byte is paged as complete
* hexadecimal. Page boundaries use the OLED renderer's actual font and
* word-wrap budget, so no accepted byte can be clipped below the third row.
*/
bool confirm_bytes(ButtonRequestType button_request, const char* title,
const uint8_t* data, size_t size);
bool confirm_cosmos_address(const char* desc, const char* address);
bool confirm_osmosis_address(const char* desc, const char* address);
bool confirm_ethereum_address(const char* desc, const char* address);
Expand Down
5 changes: 4 additions & 1 deletion include/keepkey/firmware/authenticator.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#define ACCOUNT_SIZE 12 // allow 11 chars for account string
#define AUTHSECRET_SIZE_MAX \
20 // 128-bit key len is the recommended minimum, this is room for 160-bit
#define AUTHSECRET_SIZE_MIN 16 // reject brute-forceable TOTP secrets
#define AUTHDATA_SIZE \
10 // WARNING: This value must be coordinated with the size of uint8_t
// encrypted_sec[] in in lib/firmware/storage.h and the storage version
Expand All @@ -41,6 +42,8 @@ enum AUTH_ERR_TYPE {
LARGESEED,
BADPASS,
UNKERR,
DUPLICATE,
AUTH_CANCELLED,
NUM_AUTHERRS
};

Expand Down Expand Up @@ -68,7 +71,7 @@ unsigned generateOTP(char* accountWithMsg, char otpStr[]);
unsigned addAuthAccount(char* accountWithSeed);
unsigned getAuthAccount(const char* slotStr, char acc[]);
unsigned removeAuthAccount(char* domAcc);
void wipeAuthData(void);
unsigned wipeAuthData(void);
#if DEBUG_LINK
void getAuthSlot(char* authSlotData);
#endif
Expand Down
4 changes: 4 additions & 0 deletions include/keepkey/firmware/binance.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ typedef struct _BinanceTransferMsg BinanceTransferMsg;
typedef struct _BinanceTransferMsg_BinanceInputOutput BinanceInputOutput;
typedef struct _BinanceTransferMsg_BinanceCoin BinanceCoin;

#define BINANCE_MAX_DENOM_LEN 31

bool binance_isValidDenom(const char* denom);
bool binance_validateTransfer(const BinanceTransferMsg* transfer);
bool binance_signTxInit(const HDNode* _node, const BinanceSignTx* _msg);
bool binance_serializeCoin(const BinanceCoin* coin);
bool binance_serializeInputOutput(const BinanceInputOutput* io);
Expand Down
11 changes: 8 additions & 3 deletions include/keepkey/firmware/eip712.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
Parser wants to see C strings, not javascript strings:
requires all complete json message strings to be enclosed by braces,
i.e., { ... } Cannot have entire json string quoted, i.e., "{ ... }" will not
work. Remove all quote escape chars, e.g., {"types": not {\"types\": int
values must be hex. Negative sign indicates negative value, e.g., -5, -8a67
Note: Do not prefix ints or uints with 0x
work. Remove all quote escape chars, e.g., {"types": not {\"types\":
Integer values must use canonical base-10 digits. Negative values use a
leading minus sign. Do not prefix ints or uints with 0x.
All hex and byte strings must be big-endian
Byte strings and address should be prefixed by 0x
*/
Expand Down Expand Up @@ -102,4 +102,9 @@ typedef enum { DOMAIN = 1, MESSAGE } dm;
int encode(const json_t* jsonTypes, const json_t* jsonVals, const char* typeS,
uint8_t* hashRet);

/* Exposed for strict-value regression tests. */
int encAddress(const char* string, uint8_t* encoded);
int encodeBytes(const char* string, uint8_t* encoded);
int encodeBytesN(const char* typeT, const char* string, uint8_t* encoded);

#endif
3 changes: 3 additions & 0 deletions include/keepkey/firmware/eos.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ uint32_t eos_actionsRemaining(void);

bool eos_hasActionUnknownDataRemaining(void);

bool eos_isSupportedAction(const EosActionCommon* common);
bool eos_unknownActionPolicyAllows(bool advanced_mode);

/// \returns true iff successful.
bool eos_compileActionUnknown(const EosActionCommon* common,
const EosActionUnknown* action);
Expand Down
2 changes: 2 additions & 0 deletions include/keepkey/firmware/ethereum.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ void bn_from_bytes(const uint8_t* value, size_t value_len, bignum256* val);
void ethereum_typed_hash_sign(const EthereumSignTypedHash* msg,
const HDNode* node,
EthereumTypedDataSignature* resp);
bool ethereum_typed_hash_policy_allows(bool advanced_mode);
bool ethereum_eip712_is_domain_primary_type(const char* primary_type);
bool ethereum_path_check(uint32_t address_n_count, const uint32_t* address_n,
bool pubkey_export, uint64_t chain);
void e712_types_values(Ethereum712TypesValues* msg,
Expand Down
3 changes: 3 additions & 0 deletions include/keepkey/firmware/ethereum_contracts/zxliquidtx.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>

#define UNISWAP_ROUTER_ADDRESS \
"\x7a\x25\x0d\x56\x30\xB4\xcF\x53\x97\x39\xdF\x2C\x5d\xAc\xb4\xc6\x59\xF2" \
Expand All @@ -31,5 +32,7 @@ typedef struct _EthereumSignTx EthereumSignTx;

bool zx_isZxLiquidTx(const EthereumSignTx* msg);
bool zx_confirmZxLiquidTx(uint32_t data_total, const EthereumSignTx* msg);
bool zx_formatZxLiquidityPrimaryAmount(const EthereumSignTx* msg, char* out,
size_t out_len);

#endif
6 changes: 6 additions & 0 deletions include/keepkey/firmware/hive.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ bool hive_slip48_path_valid_for_role(const uint32_t* address_n, size_t count,
// Matches the host serializer's cap; hived itself allows more, but eight is
// all that can be reviewed on the OLED before approval fatigue sets in.
#define HIVE_MAX_BENEFICIARIES 8
// Maximum custom_json authorization accounts accepted per operation. Every
// account is confirmed individually; bounding the set prevents an unreviewable
// approval loop and keeps the parsed transaction's static RAM use predictable.
#define HIVE_MAX_CUSTOM_JSON_AUTHS 4

// Symbol whitelist bits for the asset parser. Every asset field in the op
// table pins an explicit set — an op that accepts HIVE must never silently
Expand Down Expand Up @@ -149,6 +153,8 @@ typedef struct {
// set_withdraw_vesting_route percent)
bool is_top_level; // comment only: parent_author empty
uint8_t n_auths; // custom_json only: total auth account names
const uint8_t* auth_acct[HIVE_MAX_CUSTOM_JSON_AUTHS];
uint16_t auth_acct_len[HIVE_MAX_CUSTOM_JSON_AUTHS];

// ── Phase-3 op fields ───────────────────────────────────────────────────
// Borrowed HIVE_ASSET_LEN-byte asset slices in the op's own field order:
Expand Down
13 changes: 10 additions & 3 deletions include/keepkey/firmware/osmosis.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "trezor/crypto/bip32.h"

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

typedef struct _OsmosisSignTx OsmosisSignTx;
Expand All @@ -16,7 +17,8 @@ void debug_intermediate_hash(void);

bool osmosis_signTxInit(const HDNode* _node, const OsmosisSignTx* _msg);

bool osmosis_signTxUpdateMsgSend(const char* amount, const char* to_address);
bool osmosis_signTxUpdateMsgSend(const char* amount, const char* to_address,
const char* denom);

bool osmosis_signTxUpdateMsgDelegate(const char* amount,
const char* delegator_address,
Expand Down Expand Up @@ -67,6 +69,8 @@ bool osmosis_signTxUpdateMsgSwap(const uint64_t pool_id,
const char* token_out_min_amount);

#define OSMOSIS_PRECISION 6
#define OSMOSIS_MAX_AMOUNT_DIGITS 32
#define OSMOSIS_MAX_DENOM_LEN 68

// Longest amount a confirm screen renders: the digits, a point, a space and
// the longest denom a message can carry.
Expand All @@ -77,9 +81,12 @@ bool osmosis_signTxUpdateMsgSwap(const uint64_t pool_id,
* ("1500000", "uosmo") -> "1.500000 OSMO".
*
* Only uosmo is scaled — any other denom is shown exactly as the chain states
* it, because the device does not know its precision.
* it, because the device does not know its precision. Returns false unless the
* amount is a canonical, schema-bounded unsigned decimal and the denomination
* is a schema-bounded Cosmos asset identifier. Native uosmo additionally must
* fit uint64, which is the range accepted by the native-asset display policy.
*/
void osmosis_formatAmount(char* out, size_t out_len, const char* value,
bool osmosis_formatAmount(char* out, size_t out_len, const char* value,
const char* denom);

bool osmosis_signTxFinalize(uint8_t* public_key, uint8_t* signature);
Expand Down
15 changes: 12 additions & 3 deletions include/keepkey/firmware/signtx_tendermint.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@

typedef struct _TendermintSignTx TendermintSignTx;

typedef enum {
TENDERMINT_SIGNING_NONE = 0,
TENDERMINT_SIGNING_COSMOS,
TENDERMINT_SIGNING_GENERIC,
} TendermintSigningType;

bool tendermint_signTxInit(const HDNode* _node, const void* _msg,
const size_t msgsize, const char* denom);
const size_t msgsize, const char* denom,
TendermintSigningType type);
bool tendermint_signTxUpdateMsgSend(const uint64_t amount,
const char* to_address,
const char* chainstr, const char* denom,
Expand Down Expand Up @@ -41,9 +48,11 @@ bool tendermint_signTxUpdateMsgIBCTransfer(
const char* revision_number, const char* revision_height,
const char* chainstr, const char* denom, const char* msgTypePrefix);
bool tendermint_signTxFinalize(uint8_t* public_key, uint8_t* signature);
bool tendermint_signingIsInited(void);
bool tendermint_signingIsInited(TendermintSigningType type);
bool tendermint_signingConfigMatches(const char* chain_name, const char* denom,
const char* message_type_prefix);
bool tendermint_signingIsFinished(void);
void tendermint_signAbort(void);
const void* tendermint_getSignTx(void);

#endif
#endif
5 changes: 4 additions & 1 deletion include/keepkey/firmware/tiny-json.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#define json_containerOf(ptr, type, member) \
((type*)((char*)ptr - offsetof(type, member)))

Expand Down Expand Up @@ -66,7 +70,6 @@ typedef struct json_s {
jsonType_t type;
} json_t;

extern int errno;
/** Parse a string to get a json.
* @param str String pointer with a JSON object. It will be modified.
* @param mem Array of json properties to allocate.
Expand Down
44 changes: 30 additions & 14 deletions lib/board/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "keepkey/board/font.h"

#include <stddef.h>
#include <string.h>

/* --- Image Font ------------------------------------------------------------
*/
Expand Down Expand Up @@ -2598,29 +2599,31 @@ uint32_t calc_str_width(const Font* font, const char* str) {
* OUTPUT
* line count
*/
uint32_t calc_str_line(const Font* font, const char* str, uint16_t line_width) {
uint32_t calc_str_line_n(const Font* font, const char* str, size_t str_len,
uint16_t line_width) {
uint8_t line_count = 1;
uint16_t x_offset = 0;
size_t offset = 0;

while (*str) {
uint8_t character_width = font_get_char(font, str[0])->width;
while (offset < str_len && str[offset]) {
uint8_t character_width = font_get_char(font, str[offset])->width;
uint16_t word_width = character_width;
const char* next_character = str + 1;
size_t next_offset = offset + 1;

/* Allow line breaks */
if (*str == '\n') {
if (str[offset] == '\n') {
line_count++;
x_offset = 0;
str++;
offset++;
continue;
}

/* Calculate next work width */
if (*str == ' ') {
while (*next_character && *next_character != ' ' &&
*next_character != '\n') {
word_width += font_get_char(font, *next_character)->width;
next_character++;
if (str[offset] == ' ') {
while (next_offset < str_len && str[next_offset] &&
str[next_offset] != ' ' && str[next_offset] != '\n') {
word_width += font_get_char(font, str[next_offset])->width;
next_offset++;
}
}

Expand All @@ -2631,14 +2634,27 @@ uint32_t calc_str_line(const Font* font, const char* str, uint16_t line_width) {
}

/* Remove leading spaces */
if (x_offset == 0 && *str == ' ') {
str++;
if (x_offset == 0 && str[offset] == ' ') {
offset++;
continue;
}

x_offset += character_width;
str++;
offset++;
}

return line_count;
}

uint32_t calc_str_line(const Font* font, const char* str, uint16_t line_width) {
return calc_str_line_n(font, str, strlen(str), line_width);
}

size_t calc_str_page(const Font* font, const char* str, size_t str_len,
uint16_t line_width, uint32_t max_lines) {
size_t best = 0;
for (size_t take = 1; take <= str_len; take++) {
if (calc_str_line_n(font, str, take, line_width) <= max_lines) best = take;
}
return best;
}
Loading
Loading