Skip to content

Commit

Permalink
Merge pull request #700 from LedgerHQ/cev/add_fuzzing
Browse files Browse the repository at this point in the history
Add 1st fuzzing
  • Loading branch information
cedelavergne-ledger authored Jan 6, 2025
2 parents 619d7cd + 0ff2f94 commit 906f640
Show file tree
Hide file tree
Showing 22 changed files with 800 additions and 14 deletions.
17 changes: 17 additions & 0 deletions .clusterfuzzlite/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest AS LITE_BUILDER

# Base image with clang toolchain
FROM gcr.io/oss-fuzz-base/base-builder:v1

# Copy the project's source code.
COPY . $SRC/app-ethereum
COPY --from=LITE_BUILDER /opt/ledger-secure-sdk $SRC/app-ethereum/BOLOS_SDK

# Add the ethereum-plugin-sdk submodule
RUN git clone https://github.com/LedgerHQ/ethereum-plugin-sdk.git $SRC/app-ethereum/ethereum-plugin-sdk

# Working directory for build.sh
WORKDIR $SRC/app-ethereum

# Copy build.sh into $SRC dir.
COPY ./.clusterfuzzlite/build.sh $SRC/
9 changes: 9 additions & 0 deletions .clusterfuzzlite/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash -eu

# build fuzzers

pushd tests/fuzzing
cmake -DBOLOS_SDK=$(pwd)/../../BOLOS_SDK -B build -S .
cmake --build build
mv ./build/fuzzer "${OUT}"
popd
1 change: 1 addition & 0 deletions .clusterfuzzlite/project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
language: c
40 changes: 40 additions & 0 deletions .github/workflows/cflite_cron.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: ClusterFuzzLite cron tasks
on:
workflow_dispatch:
push:
branches:
- main # Use your actual default branch here.
schedule:
- cron: '0 13 * * 6' # At 01:00 PM, only on Saturday
permissions: read-all
jobs:
Fuzzing:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- mode: batch
sanitizer: address
- mode: batch
sanitizer: memory
- mode: prune
sanitizer: address
- mode: coverage
sanitizer: coverage
steps:
- name: Build Fuzzers (${{ matrix.mode }} - ${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
language: c # Change this to the language you are fuzzing.

Check warning on line 31 in .github/workflows/cflite_cron.yml

View workflow job for this annotation

GitHub Actions / Check yaml files

31:23 [comments] too few spaces before comment
sanitizer: ${{ matrix.sanitizer }}
- name: Run Fuzzers (${{ matrix.mode }} - ${{ matrix.sanitizer }})
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 300 # 5 minutes

Check warning on line 38 in .github/workflows/cflite_cron.yml

View workflow job for this annotation

GitHub Actions / Check yaml files

38:29 [comments] too few spaces before comment
mode: ${{ matrix.mode }}
sanitizer: ${{ matrix.sanitizer }}
43 changes: 43 additions & 0 deletions .github/workflows/cflite_pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: ClusterFuzzLite PR fuzzing
on:
pull_request:
paths:
- '**'
permissions: read-all
jobs:
PR:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
sanitizer: [address, undefined, memory] # Override this with the sanitizers you want.
steps:
- name: Build Fuzzers (${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
language: c # Change this to the language you are fuzzing.
github-token: ${{ secrets.GITHUB_TOKEN }}
sanitizer: ${{ matrix.sanitizer }}
# Optional but recommended: used to only run fuzzers that are affected
# by the PR.
# storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git
# storage-repo-branch: main # Optional. Defaults to "main"
# storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages".
- name: Run Fuzzers (${{ matrix.sanitizer }})
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 300 # 5 minutes
mode: 'code-change'
sanitizer: ${{ matrix.sanitizer }}
output-sarif: true
# Optional but recommended: used to download the corpus produced by
# batch fuzzing.
# storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git
# storage-repo-branch: main # Optional. Defaults to "main"
# storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages".
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@ __version__.py

.vscode
.idea

# Fuzzing
tests/fuzzing/corpus/
tests/fuzzing/out/
default.profraw
default.profdata
fuzz-*.log
crash-*
report.html
2 changes: 1 addition & 1 deletion src/shared_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "nbgl_types.h"
#endif

extern void app_exit();
extern void app_exit(void);
extern void common_app_init(void);

#define SELECTOR_LENGTH 4
Expand Down
1 change: 1 addition & 0 deletions src_features/generic_tx_parser/cmd_tx_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define CMD_TX_INFO_H_

#include <stdint.h>
#include "gtp_tx_info.h"

uint16_t handle_tx_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload);
void gcs_cleanup(void);
Expand Down
2 changes: 1 addition & 1 deletion src_features/generic_tx_parser/gtp_param_datetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ bool format_param_datetime(const s_param_datetime *param, const char *name) {
s_parsed_value_collection collec;
char *buf = strings.tmp.tmp;
size_t buf_size = sizeof(strings.tmp.tmp);
uint8_t time_buf[sizeof(uint32_t)];
uint8_t time_buf[sizeof(uint32_t)] = {0};
time_t timestamp;
uint256_t block_height;

Expand Down
2 changes: 1 addition & 1 deletion src_features/generic_tx_parser/gtp_param_duration.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ bool format_param_duration(const s_param_duration *param, const char *name) {
uint8_t minutes;
uint8_t seconds;
uint64_t remaining;
uint8_t raw_buf[sizeof(remaining)];
uint8_t raw_buf[sizeof(remaining)] = {0};
int off;

if (!value_get(&param->value, &collec)) {
Expand Down
2 changes: 1 addition & 1 deletion src_features/generic_tx_parser/gtp_param_trusted_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ bool format_param_trusted_name(const s_param_trusted_name *param, const char *na
char *buf = strings.tmp.tmp;
size_t buf_size = sizeof(strings.tmp.tmp);
uint64_t chain_id;
uint8_t addr[ADDRESS_LENGTH];
uint8_t addr[ADDRESS_LENGTH] = {0};
const char *tname;
e_param_type param_type;

Expand Down
6 changes: 3 additions & 3 deletions src_features/generic_tx_parser/gtp_tx_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static bool handle_version(const s_tlv_data *data, s_tx_info_ctx *context) {

static bool handle_chain_id(const s_tlv_data *data, s_tx_info_ctx *context) {
uint64_t chain_id;
uint8_t buf[sizeof(chain_id)];
uint8_t buf[sizeof(chain_id)] = {0};

if (data->length > sizeof(buf)) {
return false;
Expand All @@ -72,7 +72,7 @@ static bool handle_chain_id(const s_tlv_data *data, s_tx_info_ctx *context) {
}

static bool handle_contract_addr(const s_tlv_data *data, s_tx_info_ctx *context) {
uint8_t buf[ADDRESS_LENGTH];
uint8_t buf[ADDRESS_LENGTH] = {0};

if (data->length > sizeof(buf)) {
return false;
Expand Down Expand Up @@ -165,7 +165,7 @@ static bool handle_contract_name(const s_tlv_data *data, s_tx_info_ctx *context)
}

static bool handle_deploy_date(const s_tlv_data *data, s_tx_info_ctx *context) {
uint8_t buf[sizeof(uint32_t)];
uint8_t buf[sizeof(uint32_t)] = {0};
time_t timestamp;

if (data->length > sizeof(buf)) {
Expand Down
25 changes: 21 additions & 4 deletions src_features/provideDynamicNetwork/network_dynamic.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ static uint16_t parse_icon_buffer(void) {
uint8_t digest[CX_SHA256_SIZE];
const uint8_t *data = g_network_icon[g_current_slot].bitmap;
const uint16_t field_len = g_icon_payload.received_size;
cx_err_t error = CX_INTERNAL_ERROR;

// Check the icon header
sw = check_icon_header(data, field_len, &img_len);
Expand All @@ -298,7 +299,7 @@ static uint16_t parse_icon_buffer(void) {
CHECK_FIELD_OVERFLOW("NETWORK_ICON", g_network_icon[g_current_slot].bitmap);

// Check icon hash
cx_sha256_hash(data, field_len, digest);
CX_CHECK(cx_sha256_hash(data, field_len, digest));
if (memcmp(digest, g_network_icon[g_current_slot].hash, CX_SHA256_SIZE) != 0) {
PRINTF("NETWORK_ICON hash mismatch!\n");
return APDU_RESPONSE_INVALID_DATA;
Expand All @@ -313,7 +314,9 @@ static uint16_t parse_icon_buffer(void) {
DYNAMIC_NETWORK_INFO[g_current_slot].icon.isFile = true;
COPY_FIELD(DYNAMIC_NETWORK_INFO[g_current_slot].icon.bitmap);
print_icon_info();
return APDU_RESPONSE_OK;
error = APDU_RESPONSE_OK;
end:
return error;
}

/**
Expand Down Expand Up @@ -376,6 +379,12 @@ static uint16_t handle_next_icon_chunk(const uint8_t *data, uint8_t length) {
*/
static uint16_t handle_icon_chunks(uint8_t p1, const uint8_t *data, uint8_t length) {
uint16_t sw = APDU_RESPONSE_UNKNOWN;
uint8_t hash[CX_SHA256_SIZE] = {0};

if (memcmp(g_network_icon[g_current_slot].hash, hash, CX_SHA256_SIZE) == 0) {
PRINTF("Error: Icon hash not set!\n");
return APDU_RESPONSE_INVALID_DATA;
}

// Check the received chunk index
if (p1 == P1_FIRST_CHUNK) {
Expand Down Expand Up @@ -432,16 +441,24 @@ static bool verify_signature(s_sig_ctx *sig_ctx) {
CX_CHECK(
cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH));

#ifdef HAVE_LEDGER_PKI
CX_CHECK(check_signature_with_pubkey("Dynamic Network",
hash,
sizeof(hash),
LEDGER_SIGNATURE_PUBLIC_KEY,
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
#ifdef HAVE_LEDGER_PKI
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
#endif
(uint8_t *) (sig_ctx->sig),
sig_ctx->sig_size));
#else
CX_CHECK(check_signature_with_pubkey("Dynamic Network",
hash,
sizeof(hash),
LEDGER_SIGNATURE_PUBLIC_KEY,
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
(uint8_t *) (sig_ctx->sig),
sig_ctx->sig_size));
#endif

ret_code = true;
end:
Expand Down
2 changes: 1 addition & 1 deletion src_features/provideTrustedName/cmd_provide_trusted_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ static bool parse_tlv(const s_tlv_payload *payload,
{.tag = NFT_ID, .func = &handle_nft_id},
};
e_tlv_step step = TLV_TAG;
s_tlv_data data;
s_tlv_data data = {0};
size_t offset = 0;
size_t tag_start_off;

Expand Down
2 changes: 1 addition & 1 deletion src_features/provide_enum_value/enum_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static bool handle_version(const s_tlv_data *data, s_enum_value_ctx *context) {
}

static bool handle_chain_id(const s_tlv_data *data, s_enum_value_ctx *context) {
uint8_t buf[sizeof(context->enum_value.entry.chain_id)];
uint8_t buf[sizeof(context->enum_value.entry.chain_id)] = {0};

if (data->length > sizeof(buf)) {
return false;
Expand Down
2 changes: 1 addition & 1 deletion src_features/signTx/logic_signTx.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ __attribute__((noreturn)) void send_swap_error(uint8_t error_code,
const char *str1,
const char *str2) {
uint32_t tx = 0;
uint len = 0;
size_t len = 0;
PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED: 0x%x\n", error_code);
// Set RAPDU error codes
G_io_apdu_buffer[tx++] = error_code;
Expand Down
Loading

0 comments on commit 906f640

Please sign in to comment.