Audit-clean C standard across all 5 cb challenges: fix 3 functions over 8 exec lines; rebuild bins; update CB-0x03 and CB-0x05 guides; verify all guides against new bins

This commit is contained in:
Kevin Thomas committed 2026-10-11 17:43:45 -04:00
1 parent 4ade66738f
commit 23b9f628ef
51 files changed
+3744 -7904

No files matched your search

+118 -21
View File
@@ -2,6 +2,9 @@
//
// Copyright (c) 2026 Kevin Thomas
//
// Author: Kevin Thomas
// Email: kevin@mytechnotalent.com
// GitHub: https://github.com/mytechnotalent
// File: aes.c
// Desc: Minimal AES-128-ECB block decryption for the CTF waypoint.
// Created: 2026
@@ -50,9 +53,26 @@ static const uint8_t rsbox[256] = {
static const uint8_t Rcon[11] = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36};
static uint8_t xtime(uint8_t x) { return (uint8_t)((x << 1) ^ (((x >> 7) & 1) * 0x1B)); }
/**
* @brief Multiply a byte by two in GF(2^8) (AES xtime operation).
*
* @param x Byte to multiply by the polynomial x.
* @return uint8_t Doubled byte reduced modulo the AES polynomial.
*/
static uint8_t xtime(uint8_t x)
{
return (uint8_t)((x << 1) ^ (((x >> 7) & 1) * 0x1B));
}
static uint8_t mul(uint8_t a, uint8_t b) {
/**
* @brief Multiply two bytes in GF(2^8) with the AES polynomial.
*
* @param a Multiplicand byte.
* @param b Multiplier byte.
* @return uint8_t Product byte reduced modulo the AES polynomial.
*/
static uint8_t mul(uint8_t a, uint8_t b)
{
uint8_t p = 0;
for (int i = 0; i < 8; i++) {
if (b & 1) p ^= a;
@@ -63,36 +83,101 @@ static uint8_t mul(uint8_t a, uint8_t b) {
return p;
}
static void key_expansion(const uint8_t *key, uint8_t *rk) {
/**
* @brief Rotate and substitute a schedule word, then apply Rcon.
*
* @param t Four-byte schedule word to transform in place.
* @param i Round-key word index selecting the Rcon constant.
* @return None.
*/
static void rot_sub_word(uint8_t *t, int i)
{
uint8_t tmp = t[0];
t[0] = (uint8_t)(sbox[t[1]] ^ Rcon[i / 4]);
t[1] = sbox[t[2]];
t[2] = sbox[t[3]];
t[3] = sbox[tmp];
}
/**
* @brief XOR a schedule word into the next round-key word.
*
* @param i Round-key word index being generated.
* @param t Transformed previous word bytes.
* @param rk Round-key buffer holding 44 words.
* @return None.
*/
static void xor_round_word(int i, const uint8_t *t, uint8_t *rk)
{
for (int j = 0; j < 4; j++)
rk[i * 4 + j] = rk[(i - 4) * 4 + j] ^ t[j];
}
/**
* @brief Expand the 16-byte cipher key into the round-key schedule.
*
* @param key 16-byte AES-128 cipher key.
* @param rk Output buffer for 176 bytes of round keys.
* @return None.
*/
static void key_expansion(const uint8_t *key, uint8_t *rk)
{
memcpy(rk, key, 16);
for (int i = 4; i < 44; i++) {
uint8_t t[4];
memcpy(t, &rk[(i - 1) * 4], 4);
if (i % 4 == 0) {
uint8_t tmp = t[0];
t[0] = (uint8_t)(sbox[t[1]] ^ Rcon[i / 4]);
t[1] = sbox[t[2]];
t[2] = sbox[t[3]];
t[3] = sbox[tmp];
}
for (int j = 0; j < 4; j++) rk[i * 4 + j] = rk[(i - 4) * 4 + j] ^ t[j];
if (i % 4 == 0)
rot_sub_word(t, i);
xor_round_word(i, t, rk);
}
}
static void add_round_key(uint8_t r, uint8_t *s, const uint8_t *rk) {
/**
* @brief XOR one 16-byte round key into the cipher state.
*
* @param r Round number selecting the round key.
* @param s Sixteen-byte cipher state, updated in place.
* @param rk Round-key schedule produced by key_expansion.
* @return None.
*/
static void add_round_key(uint8_t r, uint8_t *s, const uint8_t *rk)
{
for (int i = 0; i < 16; i++) s[i] ^= rk[r * 16 + i];
}
static void inv_sub_bytes(uint8_t *s) { for (int i = 0; i < 16; i++) s[i] = rsbox[s[i]]; }
/**
* @brief Apply the inverse S-box to every state byte.
*
* @param s Sixteen-byte cipher state, updated in place.
* @return None.
*/
static void inv_sub_bytes(uint8_t *s)
{
for (int i = 0; i < 16; i++) s[i] = rsbox[s[i]];
}
static void inv_shift_rows(uint8_t *s) {
/**
* @brief Cyclically shift state rows for inverse ShiftRows.
*
* @param s Sixteen-byte cipher state, updated in place.
* @return None.
*/
static void inv_shift_rows(uint8_t *s)
{
uint8_t t;
t = s[13]; s[13] = s[9]; s[9] = s[5]; s[5] = s[1]; s[1] = t;
t = s[2]; s[2] = s[10]; s[10] = t; t = s[6]; s[6] = s[14]; s[14] = t;
t = s[3]; s[3] = s[7]; s[7] = s[11]; s[11] = s[15]; s[15] = t;
}
static void inv_mix_columns(uint8_t *s) {
/**
* @brief Mix each state column with the inverse MDS matrix.
*
* @param s Sixteen-byte cipher state, updated in place.
* @return None.
*/
static void inv_mix_columns(uint8_t *s)
{
for (int i = 0; i < 4; i++) {
uint8_t a = s[i * 4], b = s[i * 4 + 1], c = s[i * 4 + 2], d = s[i * 4 + 3];
s[i * 4] = (uint8_t)(mul(a, 14) ^ mul(b, 11) ^ mul(c, 13) ^ mul(d, 9));
@@ -102,17 +187,29 @@ static void inv_mix_columns(uint8_t *s) {
}
}
/**
* @brief Run AES decryption rounds nine through one on the state.
*
* @param s Sixteen-byte cipher state, updated in place.
* @param rk Round-key schedule produced by key_expansion.
* @return None.
*/
static void decrypt_rounds(uint8_t *s, const uint8_t *rk)
{
for (int r = 9; r > 0; r--) {
inv_shift_rows(s);
inv_sub_bytes(s);
add_round_key(r, s, rk);
inv_mix_columns(s);
}
}
void aes128_ecb_decrypt_block(const uint8_t in[16], const uint8_t key[16], uint8_t out[16]) {
uint8_t rk[176];
key_expansion(key, rk);
memcpy(out, in, 16);
add_round_key(10, out, rk);
for (int r = 9; r > 0; r--) {
inv_shift_rows(out);
inv_sub_bytes(out);
add_round_key(r, out, rk);
inv_mix_columns(out);
}
decrypt_rounds(out, rk);
inv_shift_rows(out);
inv_sub_bytes(out);
add_round_key(0, out, rk);
+7
View File
@@ -148,6 +148,13 @@ static bool process_gps_char(char ch, double *lat, double *lon)
return false;
}
/**
* @brief Read one GPS byte from the PIO FIFO and process it.
*
* @param lat Pointer to current latitude.
* @param lon Pointer to current longitude.
* @return bool True if a valid active 3D fix was parsed, false otherwise.
*/
static bool handle_gps_byte(double *lat, double *lon)
{
char ch = (char)(pio_sm_get(GPS_PIO, GPS_SM) >> 24);
+63
View File
@@ -40,12 +40,24 @@
static uint8_t lcd_addr = 0x27;
static bool lcd_ready = false;
/**
* @brief Write one byte to the PCF8574 expander when the LCD is ready.
*
* @param d Byte to write to the expander.
* @return None.
*/
static void pcf_write(uint8_t d)
{
if (lcd_ready)
i2c_write_blocking(LCD_I2C_INST, lcd_addr, &d, 1, false);
}
/**
* @brief Pulse the enable line to latch a byte into the HD44780.
*
* @param d Byte value carrying data and control bits.
* @return None.
*/
static void pcf_pulse(uint8_t d)
{
pcf_write(d | PIN_EN);
@@ -54,6 +66,13 @@ static void pcf_pulse(uint8_t d)
sleep_us(50);
}
/**
* @brief Write one 4-bit nibble with register select and backlight.
*
* @param n Nibble value carried in the low four bits.
* @param mode Register select (0 command, 1 data).
* @return None.
*/
static void lcd_write4(uint8_t n, uint8_t mode)
{
uint8_t d = (n & 0x0F) << 4;
@@ -62,30 +81,62 @@ static void lcd_write4(uint8_t n, uint8_t mode)
pcf_pulse(d);
}
/**
* @brief Send one byte to the HD44780 as two nibbles.
*
* @param v Byte value to send.
* @param mode Register select (0 command, 1 data).
* @return None.
*/
static void lcd_send(uint8_t v, uint8_t mode)
{
lcd_write4((v >> 4) & 0x0F, mode);
lcd_write4(v & 0x0F, mode);
}
/**
* @brief Clear the display and return the cursor home.
*
* @param void No parameters.
* @return None.
*/
static void lcd_clear(void)
{
lcd_send(0x01, 0);
sleep_ms(2);
}
/**
* @brief Position the display cursor at a row and column.
*
* @param row Display row (0 or 1).
* @param col Display column.
* @return None.
*/
static void lcd_set_cursor(int row, int col)
{
uint8_t offset = (row == 0) ? 0x00 : 0x40;
lcd_send(0x80 | (col + offset), 0);
}
/**
* @brief Write a NUL-terminated string to the display.
*
* @param s String to write at the current cursor position.
* @return None.
*/
static void lcd_puts(const char *s)
{
while (*s)
lcd_send((uint8_t)*s++, 1);
}
/**
* @brief Run the HD44780 4-bit interface reset sequence.
*
* @param void No parameters.
* @return None.
*/
static void lcd_reset_seq(void)
{
lcd_write4(0x03, 0); sleep_ms(5);
@@ -94,6 +145,12 @@ static void lcd_reset_seq(void)
lcd_write4(0x02, 0); sleep_us(150);
}
/**
* @brief Run the HD44780 display configuration sequence.
*
* @param void No parameters.
* @return None.
*/
static void lcd_cfg_seq(void)
{
lcd_send(0x28, 0);
@@ -102,6 +159,12 @@ static void lcd_cfg_seq(void)
lcd_send(0x06, 0);
}
/**
* @brief Probe the I2C bus for a known LCD expander address.
*
* @param void No parameters.
* @return bool True when a display answered, false otherwise.
*/
static bool detect_lcd(void)
{
uint8_t rx;
+18
View File
@@ -33,6 +33,12 @@
#include <stdio.h>
#include <string.h>
/**
* @brief Drain readable LoRa UART bytes and echo printable ones.
*
* @param void No parameters.
* @return None.
*/
static void drain_lora_rx(void)
{
while (uart_is_readable(LORA_UART)) {
@@ -42,6 +48,12 @@ static void drain_lora_rx(void)
}
}
/**
* @brief Send one AT command and drain its reply.
*
* @param cmd NUL-terminated AT command string.
* @return None.
*/
static void send_at_cmd(const char *cmd)
{
uart_write_blocking(LORA_UART, (const uint8_t *)cmd, strlen(cmd));
@@ -49,6 +61,12 @@ static void send_at_cmd(const char *cmd)
drain_lora_rx();
}
/**
* @brief Configure the RYLR998 radio parameters over AT commands.
*
* @param void No parameters.
* @return None.
*/
static void configure_lora_rf(void)
{
sleep_ms(1500);
+53 -17
View File
@@ -72,31 +72,67 @@ static bool update_position(double *cur_lat, double *cur_lon)
return got_fix;
}
static void step_mission(double *cur_lat, double *cur_lon)
/**
* @brief Update the fix-hold countdown from the latest poll result.
*
* @param fix True when an active 3D lock was parsed this tick.
* @return bool True when a fix is current or still held.
*/
static bool track_fix(bool fix)
{
int siv = 0, cno = 0;
static int hold = 0;
bool fix = update_position(cur_lat, cur_lon);
gps_get_stats(&siv, &cno);
hold = fix ? 3 : ((hold > 0) ? (hold - 1) : 0);
bool have = fix || (hold > 0);
set_gnss_leds(have, siv);
if (have) {
lcd_show_coords(*cur_lat, *cur_lon);
navigate_to_target(*cur_lat, *cur_lon);
} else {
lcd_show_gnss(siv, cno);
propeller_stop();
send_telemetry(*cur_lat, *cur_lon);
}
return fix || (hold > 0);
}
/**
* @brief Autonomous micro-UAV firmware execution loop.
* @brief Execute guidance actions while a position fix is held.
*
* @param None.
* @return int Standard exit code (never reached in embedded firmware).
* @param cur_lat Pointer to current latitude.
* @param cur_lon Pointer to current longitude.
* @return None.
*/
static void run_guided(double *cur_lat, double *cur_lon)
{
lcd_show_coords(*cur_lat, *cur_lon);
navigate_to_target(*cur_lat, *cur_lon);
}
/**
* @brief Execute fallback actions while no position fix is held.
*
* @param siv Satellites in view.
* @param cno Best carrier-to-noise density.
* @param cur_lat Pointer to current latitude.
* @param cur_lon Pointer to current longitude.
* @return None.
*/
static void run_unguided(int siv, int cno, double *cur_lat, double *cur_lon)
{
lcd_show_gnss(siv, cno);
propeller_stop();
send_telemetry(*cur_lat, *cur_lon);
}
/**
* @brief Advance the mission by one flight tick.
*
* @param cur_lat Pointer to current latitude.
* @param cur_lon Pointer to current longitude.
* @return None.
*/
static void step_mission(double *cur_lat, double *cur_lon)
{
bool have = track_fix(update_position(cur_lat, cur_lon));
int siv = 0, cno = 0;
gps_get_stats(&siv, &cno);
set_gnss_leds(have, siv);
if (have)
run_guided(cur_lat, cur_lon);
else
run_unguided(siv, cno, cur_lat, cur_lon);
}
int main(void)
{
double cur_lat = ORIGIN_LAT, cur_lon = ORIGIN_LON;