ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_verify_tarball.c File Reference

Streamed USTAR and gzip-framed CBT structural validation. More...

#include <stddef.h>
#include <string.h>
#include "mdl_verify_internal.h"
#include "miniz.h"
#include "ra8_attributes.h"
Include dependency graph for mdl_verify_tarball.c:

Go to the source code of this file.

Data Structures

struct  mdl_tar_stream_t
 Incremental TAR structural state. More...
struct  mdl_gzip_stream_t
 Streaming gzip inflater and nested TAR consumer. More...

Enumerations

enum  mdl_verify_tar_layout_t : uint16_t {
  k_tar_name_bytes = 100U ,
  k_tar_size_offset = 124U ,
  k_tar_size_bytes = 12U ,
  k_tar_checksum_offset = 148U ,
  k_tar_checksum_end = 156U ,
  k_tar_type_offset = 156U ,
  k_tar_block_bytes = 512U ,
  k_tar_padding_mask = 511U
}
 POSIX tar field layout and record sizing. More...
enum  mdl_verify_gzip_frame_t : uint32_t {
  k_gzip_id_one = 0x1FU ,
  k_gzip_id_two = 0x8BU ,
  k_gzip_method_deflate = 8U ,
  k_gzip_header_bytes = 10U ,
  k_gzip_trailer_bytes = 8U ,
  k_gzip_isize_offset = 4U ,
  k_gzip_min_bytes = 18U
}
 Fixed RFC 1952 framing emitted and accepted by mdl. More...
enum  mdl_verify_u32_shift_t : uint8_t {
  k_u32_byte_one_shift = 8U ,
  k_u32_byte_two_shift = 16U ,
  k_u32_byte_three_shift = 24U
}
 Byte shifts for little-endian decoding. More...

Functions

static ra8_err_t internal_io_read_exact (mdl_verify_io_t *io, uint8_t *destination, size_t length)
 Read one exact structural span.
static bool internal_parse_octal (const uint8_t *field, size_t length, uint64_t *out)
 Parse a bounded TAR octal field.
static ra8_err_t internal_tar_member (mdl_tar_stream_t *state)
 Validate one TAR header.
static ra8_err_t internal_tar_process_block (mdl_tar_stream_t *state)
 Process one complete 512-byte TAR block once fully buffered.
static ra8_err_t internal_tar_feed (mdl_tar_stream_t *state, const uint8_t *bytes, size_t length)
 Feed bytes into TAR validation.
static ra8_err_t internal_tar_finish (const mdl_tar_stream_t *state, mdl_verify_report_t *report)
 Finish TAR validation.
ra8_err_t priv_mdl_verify_tar (mdl_verify_io_t *io, mdl_verify_report_t *report)
 Validate an uncompressed CBT.
static uint32_t internal_get_u32le (const uint8_t *bytes)
 Decode one little-endian word.
static ra8_err_t internal_gzip_feed (mdl_gzip_stream_t *gzip, const uint8_t *bytes, uint32_t length)
 Inflate a raw-DEFLATE chunk.
static ra8_err_t internal_gzip_finish_deflate (mdl_gzip_stream_t *gzip)
 Finish raw-DEFLATE validation.
static bool internal_gzip_header_valid (const uint8_t *header)
 Validate the fixed gzip header.
static bool internal_gzip_trailer_valid (const uint8_t *trailer, const mdl_gzip_stream_t *gzip)
 Validate gzip trailer accounting.
static ra8_err_t internal_gzip_init_inflate (mdl_export_workspace_t *workspace, mdl_verify_arena_t *arena, mdl_gzip_stream_t *gzip)
 Initialize the gzip inflater bound to workspace-backed scratch.
static ra8_err_t internal_gzip_consume (mdl_verify_io_t *io, mdl_verify_arena_t *arena, mdl_gzip_stream_t *gzip, uint64_t remaining)
 Feed the compressed remainder into the inflater and validate the trailer.
ra8_err_t priv_mdl_verify_gzip_tar (mdl_verify_io_t *io, mdl_export_workspace_t *workspace, mdl_verify_report_t *report)
 Validate a gzip-compressed CBT.

Detailed Description

Streamed USTAR and gzip-framed CBT structural validation.

Assembles 512-byte USTAR records incrementally from borrowed reads and, for .cbt.gz, inflates the RFC 1952 frame into that same state machine while checking the stored CRC32 and ISIZE. No archive-sized buffer is ever retained.

[Ring 4 / Domain] {World: NS}

Since
0.1.0

Definition in file mdl_verify_tarball.c.

Enumeration Type Documentation

◆ mdl_verify_gzip_frame_t

enum mdl_verify_gzip_frame_t : uint32_t

Fixed RFC 1952 framing emitted and accepted by mdl.

Enumerator
k_gzip_id_one 

First RFC 1952 magic byte.

k_gzip_id_two 

Second RFC 1952 magic byte.

k_gzip_method_deflate 

RFC 1952 DEFLATE method identifier.

k_gzip_header_bytes 

Fixed gzip header extent.

k_gzip_trailer_bytes 

CRC32 plus ISIZE trailer extent.

k_gzip_isize_offset 

ISIZE offset inside that trailer.

k_gzip_min_bytes 

Smallest fixed-frame gzip extent.

Definition at line 36 of file mdl_verify_tarball.c.

◆ mdl_verify_tar_layout_t

enum mdl_verify_tar_layout_t : uint16_t

POSIX tar field layout and record sizing.

Enumerator
k_tar_name_bytes 

USTAR name-field extent.

k_tar_size_offset 

USTAR size-field byte offset.

k_tar_size_bytes 

USTAR size-field extent.

k_tar_checksum_offset 

USTAR checksum-field byte offset.

k_tar_checksum_end 

First byte after the checksum field.

k_tar_type_offset 

USTAR type-flag byte offset.

k_tar_block_bytes 

TAR logical record extent.

k_tar_padding_mask 

Mask used to round payloads to records.

Definition at line 24 of file mdl_verify_tarball.c.

◆ mdl_verify_u32_shift_t

enum mdl_verify_u32_shift_t : uint8_t

Byte shifts for little-endian decoding.

Enumerator
k_u32_byte_one_shift 

Shift for byte one.

k_u32_byte_two_shift 

Shift for byte two.

k_u32_byte_three_shift 

Shift for byte three.

Definition at line 47 of file mdl_verify_tarball.c.

Function Documentation

◆ internal_get_u32le()

uint32_t internal_get_u32le ( const uint8_t * bytes)
static

Decode one little-endian word.

Combines exactly four bytes without alignment assumptions.

Parameters
[in]bytesFour input bytes.
Returns
Decoded word.
Return values
UINT32_MAXWhen encoded as all ones.
Precondition
bytes spans four bytes.
bytes remains readable for the call.
Postcondition
bytes is unchanged.
The result is host-endian independent.
Note
Used by gzip trailers.
Since
v0.1.0

Definition at line 283 of file mdl_verify_tarball.c.

References k_u32_byte_one_shift, k_u32_byte_three_shift, k_u32_byte_two_shift, and RA8_INTERNAL.

Referenced by internal_gzip_trailer_valid().

◆ internal_gzip_consume()

ra8_err_t internal_gzip_consume ( mdl_verify_io_t * io,
mdl_verify_arena_t * arena,
mdl_gzip_stream_t * gzip,
uint64_t remaining )
static

Feed the compressed remainder into the inflater and validate the trailer.

Streams chunked reads until end-of-stream or remaining is exhausted, finishes any pending deflate output, then reads and checks the eight-byte gzip trailer against the streamed CRC/size.

Parameters
[in,out]ioBorrowed input positioned after the gzip header.
[in,out]arenaMiniz allocator state; inspected for exhaustion.
[in,out]gzipStream state advanced by this call.
[in]remainingCompressed bytes left to read, excluding the trailer.
Returns
Status.
Return values
k_ra8_okThe stream ended cleanly and the trailer matches.
Precondition
io is positioned at the first compressed byte.
gzip was successfully initialized by internal_gzip_init_inflate.
Postcondition
On k_ra8_ok every compressed byte and the trailer have been consumed.
Failure reports the first framing, CRC, or capacity fault.
Note
Not thread-safe for a shared input or workspace.
Since
v0.1.0

Definition at line 424 of file mdl_verify_tarball.c.

References mdl_gzip_stream_t::ended, mdl_verify_arena_t::exhausted, internal_gzip_feed(), internal_gzip_finish_deflate(), internal_gzip_trailer_valid(), internal_io_read_exact(), mdl_storage_t::io_buffer, mdl_storage_t::io_buffer_bytes, k_gzip_trailer_bytes, k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, and RA8_INTERNAL.

Referenced by priv_mdl_verify_gzip_tar().

◆ internal_gzip_feed()

ra8_err_t internal_gzip_feed ( mdl_gzip_stream_t * gzip,
const uint8_t * bytes,
uint32_t length )
static

Inflate a raw-DEFLATE chunk.

Feeds bounded decoded chunks into TAR while tracking CRC and size.

Parameters
[in,out]gzipInflate and TAR state.
[in]bytesCompressed input.
[in]lengthInput extent.
Returns
Status.
Return values
k_ra8_okWhile the stream is valid.
Precondition
gzip is initialized.
bytes is non-null even when length is zero.
Postcondition
Input is consumed or rejected.
Produced bytes update TAR and CRC.
Note
Output never exceeds its fixed chunk.
Since
v0.1.0

Definition at line 297 of file mdl_verify_tarball.c.

References mdl_gzip_stream_t::crc, mdl_gzip_stream_t::ended, internal_tar_feed(), k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, mdl_gzip_stream_t::output, mdl_gzip_stream_t::output_cap, mdl_gzip_stream_t::raw_bytes, mdl_gzip_stream_t::stream, and mdl_gzip_stream_t::tar.

Referenced by internal_gzip_consume(), and internal_gzip_finish_deflate().

◆ internal_gzip_finish_deflate()

ra8_err_t internal_gzip_finish_deflate ( mdl_gzip_stream_t * gzip)
static

Finish raw-DEFLATE validation.

Requires an explicit end marker without additional compressed bytes.

Parameters
[in,out]gzipInitialized stream state.
Returns
Status.
Return values
k_ra8_okWhen the end marker is observed.
Precondition
gzip is initialized.
All compressed input was supplied.
Postcondition
Success sets ended.
Stalls become validation failures.
Note
A non-null zero-byte sentinel avoids miniz UB.
Since
v0.1.0

Definition at line 335 of file mdl_verify_tarball.c.

References mdl_gzip_stream_t::ended, internal_gzip_feed(), k_ra8_err_validation_failed, k_ra8_ok, RA8_INTERNAL, and mdl_gzip_stream_t::stream.

Referenced by internal_gzip_consume().

◆ internal_gzip_header_valid()

bool internal_gzip_header_valid ( const uint8_t * header)
static

Validate the fixed gzip header.

Accepts DEFLATE with no optional RFC 1952 fields.

Parameters
[in]headerFixed header bytes.
Returns
Whether supported.
Return values
trueFor the accepted frame.
Precondition
header spans k_gzip_header_bytes.
header is readable.
Postcondition
header is unchanged.
The result is deterministic.
Note
Optional fields are rejected explicitly.
Since
v0.1.0

Definition at line 357 of file mdl_verify_tarball.c.

References k_gzip_id_one, k_gzip_id_two, k_gzip_method_deflate, and RA8_INTERNAL.

Referenced by priv_mdl_verify_gzip_tar().

◆ internal_gzip_init_inflate()

ra8_err_t internal_gzip_init_inflate ( mdl_export_workspace_t * workspace,
mdl_verify_arena_t * arena,
mdl_gzip_stream_t * gzip )
static

Initialize the gzip inflater bound to workspace-backed scratch.

Reserves the output buffer from workspace, wires the miniz allocator to the arena, and opens the raw-deflate inflater.

Parameters
[in,out]workspaceScratch arena backing both the output buffer and miniz's internal allocations.
[in,out]arenaMiniz allocator state bound to workspace.
[in,out]gzipStream state to initialize.
Returns
Status.
Return values
k_ra8_okThe output buffer and inflater are ready.
Precondition
gzip->output_cap and gzip->crc are already set by the caller.
workspace was reset and arena is bound to it.
Postcondition
On success gzip->output and gzip->stream are ready to feed.
Failure latches arena exhaustion and opens no inflater.
Note
Not thread-safe for a shared workspace.
Since
v0.1.0

Definition at line 391 of file mdl_verify_tarball.c.

References mdl_verify_arena_t::exhausted, k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, mdl_gzip_stream_t::output, mdl_gzip_stream_t::output_cap, priv_mdl_verify_arena_alloc(), priv_mdl_verify_arena_free(), priv_mdl_verify_workspace_take(), RA8_INTERNAL, and mdl_gzip_stream_t::stream.

Referenced by priv_mdl_verify_gzip_tar().

◆ internal_gzip_trailer_valid()

bool internal_gzip_trailer_valid ( const uint8_t * trailer,
const mdl_gzip_stream_t * gzip )
static

Validate gzip trailer accounting.

Compares stored CRC32 and ISIZE with streamed output.

Parameters
[in]trailerEight trailer bytes.
[in,out]gzipCompleted stream state.
Returns
Whether both fields match.
Return values
trueOn an exact match.
Precondition
Both pointers are valid.
raw_bytes fits RFC 1952 ISIZE policy.
Postcondition
Inputs are unchanged.
Both fields are checked.
Note
ISIZE is compared modulo uint32_t.
Since
v0.1.0

Definition at line 369 of file mdl_verify_tarball.c.

References mdl_gzip_stream_t::crc, internal_get_u32le(), k_gzip_isize_offset, RA8_INTERNAL, and mdl_gzip_stream_t::raw_bytes.

Referenced by internal_gzip_consume().

◆ internal_io_read_exact()

ra8_err_t internal_io_read_exact ( mdl_verify_io_t * io,
uint8_t * destination,
size_t length )
static

Read one exact structural span.

Maps a successful early EOF to validation failure.

Parameters
[in,out]ioOpen input.
[out]destinationOutput buffer.
[in]lengthRequired bytes.
Returns
Status.
Return values
k_ra8_okWhen length bytes arrive.
Precondition
io is open.
destination spans length bytes.
Postcondition
Success initializes the complete span.
Short EOF is explicit corruption.
Note
Backend faults are preserved.
Since
v0.1.0

Definition at line 84 of file mdl_verify_tarball.c.

References k_ra8_err_validation_failed, k_ra8_ok, and priv_mdl_verify_io_read_up_to().

Referenced by internal_gzip_consume(), and priv_mdl_verify_gzip_tar().

◆ internal_parse_octal()

bool internal_parse_octal ( const uint8_t * field,
size_t length,
uint64_t * out )
static

Parse a bounded TAR octal field.

Accepts padding but rejects non-octal data and overflow.

Parameters
[in]fieldInput field.
[in]lengthField extent.
[out]outParsed value.
Returns
Status.
Return values
k_ra8_okFor valid octal.
Precondition
field and out are valid.
field spans length bytes.
Postcondition
Success initializes out.
Failure exposes no partial value.
Note
Base-256 extensions are unsupported.
Since
v0.1.0

Definition at line 100 of file mdl_verify_tarball.c.

References RA8_INTERNAL.

Referenced by internal_tar_member().

◆ internal_tar_feed()

ra8_err_t internal_tar_feed ( mdl_tar_stream_t * state,
const uint8_t * bytes,
size_t length )
static

Feed bytes into TAR validation.

Assembles headers and skips bounded padded payloads incrementally.

Parameters
[in,out]stateIncremental state.
[in]bytesInput bytes.
[in]lengthInput extent.
Returns
Status.
Return values
k_ra8_okWhen the prefix remains valid.
Precondition
state and bytes are valid.
bytes spans length bytes.
Postcondition
Every input byte is consumed or rejected.
Counters remain bounded.
Note
Data after termination must be zero.
Since
v0.1.0

Definition at line 198 of file mdl_verify_tarball.c.

References mdl_tar_stream_t::block, mdl_tar_stream_t::block_used, mdl_tar_stream_t::ended, internal_tar_process_block(), k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, k_tar_block_bytes, memcpy(), mdl_tar_stream_t::skip_bytes, and mdl_tar_stream_t::total_bytes.

Referenced by internal_gzip_feed(), and priv_mdl_verify_tar().

◆ internal_tar_finish()

ra8_err_t internal_tar_finish ( const mdl_tar_stream_t * state,
mdl_verify_report_t * report )
static

Finish TAR validation.

Requires aligned complete termination before publishing counts.

Parameters
[in,out]stateCompleted stream state.
[in,out]reportCandidate report.
Returns
Status.
Return values
k_ra8_okFor a complete TAR.
Precondition
state and report are valid.
All source bytes were fed.
Postcondition
Success fills report counts.
Failure leaves caller output private.
Note
Two zero records are required.
Since
v0.1.0

Definition at line 241 of file mdl_verify_tarball.c.

References mdl_tar_stream_t::block_used, mdl_tar_stream_t::ended, k_ra8_err_validation_failed, k_ra8_ok, k_tar_block_bytes, mdl_tar_stream_t::members, mdl_tar_stream_t::metadata, mdl_tar_stream_t::pages, RA8_INTERNAL, mdl_tar_stream_t::skip_bytes, and mdl_tar_stream_t::total_bytes.

Referenced by priv_mdl_verify_gzip_tar(), and priv_mdl_verify_tar().

◆ internal_tar_member()

ra8_err_t internal_tar_member ( mdl_tar_stream_t * state)
static

Validate one TAR header.

Checks checksum, type, path, count, and padded payload size.

Parameters
[in,out]stateIncremental TAR state.
Returns
Status.
Return values
k_ra8_okFor a supported member.
Precondition
state holds one complete header.
state counters are bounded.
Postcondition
Success advances member accounting.
Failure stops validation.
Note
Only regular files are accepted.
Since
v0.1.0

Definition at line 128 of file mdl_verify_tarball.c.

References mdl_tar_stream_t::block, internal_parse_octal(), k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, k_tar_block_bytes, k_tar_checksum_end, k_tar_checksum_offset, k_tar_name_bytes, k_tar_padding_mask, k_tar_size_bytes, k_tar_size_offset, k_tar_type_offset, k_verify_member_max, mdl_tar_stream_t::members, memcpy(), mdl_tar_stream_t::metadata, mdl_tar_stream_t::pages, priv_mdl_verify_is_image(), priv_mdl_verify_safe_member_name(), RA8_INTERNAL, mdl_tar_stream_t::skip_bytes, and strcmp().

Referenced by internal_tar_process_block().

◆ internal_tar_process_block()

ra8_err_t internal_tar_process_block ( mdl_tar_stream_t * state)
static

Process one complete 512-byte TAR block once fully buffered.

Classifies the block as all-zero (an end-of-archive marker) or a real header, updating end-of-archive and skip-byte state.

Parameters
[in,out]stateIncremental TAR validation state with a full block.
Returns
Status.
Return values
k_ra8_okThe block was a zero marker or a valid header.
Precondition
state->block_used == k_tar_block_bytes on entry.
state is non-NULL and its member counters are bounded.
Postcondition
state->block_used is reset to zero.
A zero block advances the end-of-archive counter; a header block resets it and derives the next skip-byte count.
Note
Not thread-safe; shares the caller's incremental state.
Since
v0.1.0

Definition at line 175 of file mdl_verify_tarball.c.

References mdl_tar_stream_t::block, mdl_tar_stream_t::block_used, mdl_tar_stream_t::ended, internal_tar_member(), k_ra8_ok, k_tar_block_bytes, RA8_INTERNAL, and mdl_tar_stream_t::zero_blocks.

Referenced by internal_tar_feed().

◆ priv_mdl_verify_gzip_tar()

ra8_err_t priv_mdl_verify_gzip_tar ( mdl_verify_io_t * io,
mdl_export_workspace_t * workspace,
mdl_verify_report_t * report )

Validate a gzip-compressed CBT.

Streams raw inflate into the USTAR state machine and checks the fixed RFC 1952 framing, the stored CRC32 and ISIZE, and that no compressed byte follows the end-of-stream marker.

Parameters
[in,out]ioBorrowed open input positioned at offset zero.
[in,out]workspaceExclusive caller-owned scratch arena.
[out]reportCandidate report populated only on success.
Returns
Framing, inflate, or structural validation status.
Return values
k_ra8_okThe complete gzip frame and inner TAR were valid.
k_ra8_err_validation_failedFraming, CRC, size, or structure failed.
k_ra8_err_invalid_sizeThe scratch arena or a byte bound was exceeded.
Precondition
All pointers are non-NULL and io is open.
workspace was reset by the owning verifier.
Postcondition
The inflater is ended on every path that opened it.
Success publishes the page, member, and metadata counts.
Note
Not thread-safe for a shared input or workspace.
Since
0.1.0

Definition at line 460 of file mdl_verify_tarball.c.

References internal_gzip_consume(), internal_gzip_header_valid(), internal_gzip_init_inflate(), internal_io_read_exact(), internal_tar_finish(), k_gzip_header_bytes, k_gzip_min_bytes, k_mdl_storage_io_bytes, k_ra8_err_validation_failed, k_ra8_ok, RA8_PRIV, mdl_gzip_stream_t::stream, and mdl_gzip_stream_t::tar.

Referenced by internal_verify_borrowed().

◆ priv_mdl_verify_tar()

ra8_err_t priv_mdl_verify_tar ( mdl_verify_io_t * io,
mdl_verify_report_t * report )

Validate an uncompressed CBT.

Streams borrowed reads straight into the USTAR state machine, so no archive-sized buffer is retained for any member.

Parameters
[in,out]ioBorrowed open input positioned at offset zero.
[out]reportCandidate report populated only on success.
Returns
Structural validation status.
Return values
k_ra8_okEvery record and the terminating pair were valid.
k_ra8_err_validation_failedA record, name, or terminator was invalid.
k_ra8_err_invalid_sizeA member count or byte total exceeded its bound.
Precondition
Both pointers are non-NULL and io is open.
The bound storage supplies a nonzero I/O buffer.
Postcondition
The input remains open and its final cursor is unspecified.
Success publishes the page, member, and metadata counts.
Note
Not thread-safe for a shared input.
Since
0.1.0

Definition at line 255 of file mdl_verify_tarball.c.

References internal_tar_feed(), internal_tar_finish(), mdl_storage_t::io_buffer, mdl_storage_t::io_buffer_bytes, k_ra8_ok, priv_mdl_verify_io_read_up_to(), and RA8_PRIV.

Referenced by internal_verify_borrowed().