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
5 changes: 5 additions & 0 deletions main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ idf_component_register(
esp_driver_ppa app_update bootloader_support
)

# Ignoring a warn_unused_result return is a build error, not a warning. The
# k_quirc and cUR entry points carry the attribute and report failure that way
# and nothing else.
target_compile_options(${COMPONENT_LIB} PRIVATE -Werror=unused-result)

if(DEFINED FONT_POLICY_WIDTH AND DEFINED FONT_POLICY_HEIGHT)
find_program(PYTHON3_EXECUTABLE python3 REQUIRED)
execute_process(
Expand Down
9 changes: 5 additions & 4 deletions main/core/base43.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef BASE43_H
#define BASE43_H

#include "../utils/attributes.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Expand All @@ -21,8 +22,8 @@
*
* Returns true on success, false on invalid character or allocation failure.
*/
bool base43_decode(const char *str, size_t str_len, uint8_t **out,
size_t *out_len);
KERN_WARN_UNUSED_RESULT bool base43_decode(const char *str, size_t str_len,
uint8_t **out, size_t *out_len);

/*
* Encode bytes to a base43 string.
Expand All @@ -33,7 +34,7 @@ bool base43_decode(const char *str, size_t str_len, uint8_t **out,
*
* Returns true on success, false on allocation failure.
*/
bool base43_encode(const uint8_t *data, size_t data_len, char **out,
size_t *out_len);
KERN_WARN_UNUSED_RESULT bool base43_encode(const uint8_t *data, size_t data_len,
char **out, size_t *out_len);

#endif /* BASE43_H */
8 changes: 5 additions & 3 deletions main/core/bip322.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef BIP322_H
#define BIP322_H

#include "../utils/attributes.h"
#include <stdbool.h>

struct wally_psbt;
Expand All @@ -12,14 +13,15 @@ typedef struct {

// True if the PSBT carries the PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE (0x09)
// global field, marking it as a BIP322 message-signing request.
bool bip322_detect(const struct wally_psbt *psbt);
KERN_WARN_UNUSED_RESULT bool bip322_detect(const struct wally_psbt *psbt);

// Validates a BIP322 to_sign PSBT: structure (version-0 tx, single input at
// vout 0, single 0-value OP_RETURN output), and that the input spends the
// to_spend transaction committing to the message and the proven script.
// On success fills `out` with the message and proven address.
bool bip322_parse(const struct wally_psbt *psbt, bool is_testnet,
bip322_request_t *out);
KERN_WARN_UNUSED_RESULT bool bip322_parse(const struct wally_psbt *psbt,
bool is_testnet,
bip322_request_t *out);

void bip322_request_free(bip322_request_t *req);

Expand Down
26 changes: 16 additions & 10 deletions main/core/bip32_path.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef BIP32_PATH_H
#define BIP32_PATH_H

#include "../utils/attributes.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Expand All @@ -20,18 +21,23 @@ static inline uint32_t bip32_path_u32_le(const unsigned char *bytes) {
((uint32_t)bytes[2] << 16) | ((uint32_t)bytes[3] << 24);
}

bool bip32_path_parse(const char *path, uint32_t *components_out,
size_t *depth_out, size_t max_depth);
KERN_WARN_UNUSED_RESULT bool bip32_path_parse(const char *path,
uint32_t *components_out,
size_t *depth_out,
size_t max_depth);

bool bip32_path_format(const uint32_t *components, size_t depth, char *buf,
size_t buf_size);
KERN_WARN_UNUSED_RESULT bool bip32_path_format(const uint32_t *components,
size_t depth, char *buf,
size_t buf_size);

bool bip32_path_from_keypath(const unsigned char *raw_keypath,
size_t raw_keypath_len, uint32_t *components_out,
size_t *depth_out, size_t max_depth);
KERN_WARN_UNUSED_RESULT bool
bip32_path_from_keypath(const unsigned char *raw_keypath,
size_t raw_keypath_len, uint32_t *components_out,
size_t *depth_out, size_t max_depth);

bool bip32_path_format_keypath(const unsigned char *raw_keypath,
size_t raw_keypath_len, char *buf,
size_t buf_size, size_t max_depth);
KERN_WARN_UNUSED_RESULT bool
bip32_path_format_keypath(const unsigned char *raw_keypath,
size_t raw_keypath_len, char *buf, size_t buf_size,
size_t max_depth);

#endif // BIP32_PATH_H
73 changes: 41 additions & 32 deletions main/core/crypto_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef CRYPTO_UTILS_H
#define CRYPTO_UTILS_H

#include "../utils/attributes.h"
#include <stddef.h>
#include <stdint.h>

Expand All @@ -28,63 +29,68 @@

/* PBKDF2-HMAC-SHA256.
* Derives key_len bytes from password + salt with given iteration count. */
int crypto_pbkdf2_sha256(const uint8_t *password, size_t password_len,
const uint8_t *salt, size_t salt_len,
uint32_t iterations, uint8_t *key_out, size_t key_len);
KERN_WARN_UNUSED_RESULT int
crypto_pbkdf2_sha256(const uint8_t *password, size_t password_len,
const uint8_t *salt, size_t salt_len, uint32_t iterations,
uint8_t *key_out, size_t key_len);

/* --- Hashing --- */

/* SHA-256 hash. hash_out must be at least CRYPTO_SHA256_SIZE bytes. */
int crypto_sha256(const uint8_t *data, size_t data_len, uint8_t *hash_out);
KERN_WARN_UNUSED_RESULT int crypto_sha256(const uint8_t *data, size_t data_len,
uint8_t *hash_out);

/* --- AES-256-ECB --- */

/* Encrypt/decrypt in ECB mode. input_len must be a multiple of 16. */
int crypto_aes_ecb_encrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *input, size_t input_len,
uint8_t *output);
KERN_WARN_UNUSED_RESULT int
crypto_aes_ecb_encrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *input, size_t input_len, uint8_t *output);

int crypto_aes_ecb_decrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *input, size_t input_len,
uint8_t *output);
KERN_WARN_UNUSED_RESULT int
crypto_aes_ecb_decrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *input, size_t input_len, uint8_t *output);

/* --- AES-256-CBC --- */

/* Encrypt/decrypt in CBC mode. input_len must be a multiple of 16.
* iv is not modified (copied internally). */
int crypto_aes_cbc_encrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t iv[CRYPTO_AES_IV_SIZE],
const uint8_t *input, size_t input_len,
uint8_t *output);
KERN_WARN_UNUSED_RESULT int
crypto_aes_cbc_encrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t iv[CRYPTO_AES_IV_SIZE],
const uint8_t *input, size_t input_len, uint8_t *output);

int crypto_aes_cbc_decrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t iv[CRYPTO_AES_IV_SIZE],
const uint8_t *input, size_t input_len,
uint8_t *output);
KERN_WARN_UNUSED_RESULT int
crypto_aes_cbc_decrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t iv[CRYPTO_AES_IV_SIZE],
const uint8_t *input, size_t input_len, uint8_t *output);

/* --- AES-256-CTR --- */

/* Encrypt or decrypt in CTR mode (symmetric operation).
* nonce is 12 bytes; the 4-byte counter starts at 0. Any input_len is valid.
*/
int crypto_aes_ctr(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t nonce[CRYPTO_AES_CTR_NONCE_SIZE],
const uint8_t *input, size_t input_len, uint8_t *output);
KERN_WARN_UNUSED_RESULT int
crypto_aes_ctr(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t nonce[CRYPTO_AES_CTR_NONCE_SIZE],
const uint8_t *input, size_t input_len, uint8_t *output);

/* --- AES-256-GCM --- */

/* Encrypt with GCM authentication. tag_len can be 4-16 bytes. */
int crypto_aes_gcm_encrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *nonce, size_t nonce_len,
const uint8_t *input, size_t input_len,
uint8_t *output, uint8_t *tag, size_t tag_len);
KERN_WARN_UNUSED_RESULT int
crypto_aes_gcm_encrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *nonce, size_t nonce_len,
const uint8_t *input, size_t input_len, uint8_t *output,
uint8_t *tag, size_t tag_len);

/* Decrypt with GCM authentication verification.
* Returns CRYPTO_ERR_AUTH_FAILED if tag doesn't match. */
int crypto_aes_gcm_decrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *nonce, size_t nonce_len,
const uint8_t *input, size_t input_len,
uint8_t *output, const uint8_t *tag, size_t tag_len);
KERN_WARN_UNUSED_RESULT int
crypto_aes_gcm_decrypt(const uint8_t key[CRYPTO_AES_KEY_SIZE],
const uint8_t *nonce, size_t nonce_len,
const uint8_t *input, size_t input_len, uint8_t *output,
const uint8_t *tag, size_t tag_len);

/* --- Random --- */

Expand All @@ -95,10 +101,13 @@ void crypto_random_bytes(uint8_t *buf, size_t len);

/* Apply PKCS#7 padding. output must have room for input_len + padding (up to
* input_len + 16). Returns padded length, or 0 on error. */
size_t crypto_pkcs7_pad(const uint8_t *input, size_t input_len, uint8_t *output,
size_t output_size);
KERN_WARN_UNUSED_RESULT size_t crypto_pkcs7_pad(const uint8_t *input,
size_t input_len,
uint8_t *output,
size_t output_size);

/* Remove PKCS#7 padding in-place. Returns unpadded length, or 0 on error. */
size_t crypto_pkcs7_unpad(const uint8_t *input, size_t input_len);
KERN_WARN_UNUSED_RESULT size_t crypto_pkcs7_unpad(const uint8_t *input,
size_t input_len);

#endif // CRYPTO_UTILS_H
14 changes: 9 additions & 5 deletions main/core/descriptor_checksum.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
#include "../utils/attributes.h"
#pragma once

#include <stdbool.h>

struct wally_descriptor;

bool descriptor_string_from_descriptor(const struct wally_descriptor *desc,
char **output);
bool descriptor_checksum_from_descriptor(const struct wally_descriptor *desc,
char out[9]);
KERN_WARN_UNUSED_RESULT bool
descriptor_string_from_descriptor(const struct wally_descriptor *desc,
char **output);
KERN_WARN_UNUSED_RESULT bool
descriptor_checksum_from_descriptor(const struct wally_descriptor *desc,
char out[9]);

/* True if `s` contains an uppercase 'H' as a hardened-derivation marker
* (i.e. one or more digits at a path-component boundary — after '/', '<', or
* ';' — followed by 'H'). libwally accepts 'H', 'h', and '\'' interchangeably,
* but the canonical form used for dedup normalizes only 'h' and '\'', so
* descriptors using 'H' must be rejected at the input boundary. */
bool descriptor_text_has_uppercase_hardened(const char *s);
KERN_WARN_UNUSED_RESULT bool
descriptor_text_has_uppercase_hardened(const char *s);
4 changes: 3 additions & 1 deletion main/core/descriptor_validator.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,9 @@ static void session_register_current_descriptor(void) {

char label[REGISTRY_LABEL_MAX_LEN];
build_session_descriptor_label(label);
registry_set_label(id, label);
// The descriptor is loaded either way; without a label it lists under its id.
if (!registry_set_label(id, label))
ESP_LOGW(TAG, "Failed to label session descriptor '%s'", id);

complete_validation(VALIDATION_SUCCESS);
}
Expand Down
9 changes: 6 additions & 3 deletions main/core/descriptor_validator.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef DESCRIPTOR_VALIDATOR_H
#define DESCRIPTOR_VALIDATOR_H

#include "../utils/attributes.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -117,8 +118,9 @@ void descriptor_validate_and_load(const char *descriptor_str,
* if the descriptor parses on neither (xpub keys parse only on mainnet, tpub
* only on testnet, so the result is unambiguous for extended-key descriptors).
*/
bool descriptor_infer_network(const char *descriptor_str,
wallet_network_t *network_out);
KERN_WARN_UNUSED_RESULT bool
descriptor_infer_network(const char *descriptor_str,
wallet_network_t *network_out);

/* Watch-only (keyless) variant of descriptor_validate_and_load: validates and
* loads a descriptor for address viewing without a loaded master key. Skips the
Expand All @@ -137,6 +139,7 @@ void descriptor_validate_and_load_watch_only(
* duplicate ID is pending (e.g. result was not DUPLICATE, or the buffer is
* too small). The pending ID is reset on the next descriptor_validate_and_load
* call. */
bool descriptor_validator_get_duplicate_id(char *out, size_t out_len);
KERN_WARN_UNUSED_RESULT bool
descriptor_validator_get_duplicate_id(char *out, size_t out_len);

#endif // DESCRIPTOR_VALIDATOR_H
12 changes: 8 additions & 4 deletions main/core/fw_update.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef FW_UPDATE_H
#define FW_UPDATE_H

#include "../utils/attributes.h"
#include <stddef.h>
#include <stdint.h>

Expand All @@ -32,14 +33,17 @@ typedef void (*fw_update_progress_cb_t)(int percent, void *user_data);
/* Validate the image at path without writing anything. On success fills
* *info and returns 0; on failure returns -1 and *err_out points to a
* static human-readable reason. */
int fw_update_validate(const char *path, fw_update_info_t *info,
const char **err_out);
KERN_WARN_UNUSED_RESULT int fw_update_validate(const char *path,
fw_update_info_t *info,
const char **err_out);

/* Stream the image at path into the inactive OTA slot, verify it and set
* it as the boot partition. Returns 0 on success (caller reboots); on
* failure returns -1 with *err_out set and the current firmware untouched. */
int fw_update_apply(const char *path, fw_update_progress_cb_t progress_cb,
void *user_data, const char **err_out);
KERN_WARN_UNUSED_RESULT int fw_update_apply(const char *path,
fw_update_progress_cb_t progress_cb,
void *user_data,
const char **err_out);

/* Boot-time self-test confirmation: if the running image is pending
* verification after an update, mark it valid so the bootloader does not
Expand Down
11 changes: 6 additions & 5 deletions main/core/kef.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#ifndef KEF_H
#define KEF_H

#include "../utils/attributes.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -92,16 +93,16 @@ kef_error_t kef_parse_header(const uint8_t *envelope, size_t env_len,
void kef_encode_iterations(uint32_t effective, uint8_t out[3]);

/* Decode 3-byte stored value → effective iteration count. */
uint32_t kef_decode_iterations(const uint8_t stored[3]);
KERN_WARN_UNUSED_RESULT uint32_t kef_decode_iterations(const uint8_t stored[3]);

/* Human-readable error string. */
const char *kef_error_str(kef_error_t err);
KERN_WARN_UNUSED_RESULT const char *kef_error_str(kef_error_t err);

/*
* Check if data looks like a valid KEF envelope.
* Validates header, known version, and minimum payload size.
*/
bool kef_is_envelope(const uint8_t *data, size_t len);
KERN_WARN_UNUSED_RESULT bool kef_is_envelope(const uint8_t *data, size_t len);

/*
* Extract a raw KEF envelope from arbitrary file bytes, accepting either a raw
Expand All @@ -110,7 +111,7 @@ bool kef_is_envelope(const uint8_t *data, size_t len);
* frees) and its length via out_len, or NULL if the bytes are not a KEF
* envelope.
*/
uint8_t *kef_envelope_from_bytes(const uint8_t *data, size_t len,
size_t *out_len);
KERN_WARN_UNUSED_RESULT uint8_t *
kef_envelope_from_bytes(const uint8_t *data, size_t len, size_t *out_len);

#endif /* KEF_H */
Loading
Loading