feat: OTA-Trailer bauen und prüfen

This commit is contained in:
Michael Sauer
2026-09-12 01:16:04 +02:00
parent c96e0442c0
commit e3be3e84c1
5 changed files with 199 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
#include "util/nl_fwup_trailer.h"
#include <string.h>
/* NB: This layout is mirrored in Python at tools/mkimage/nl_mkimage.py (Task 3),
since there are two languages involved. Keep both in sync. */
#define OFF_MAGIC 0u
#define OFF_VERSION 4u
#define OFF_DEVICE 5u
#define OFF_FW 21u
#define OFF_SHA 37u
static bool copy_field(uint8_t *dst, const char *src, uint32_t len)
{
uint32_t n = (uint32_t)strlen(src);
if (n >= len)
return false;
memset(dst, 0, len);
memcpy(dst, src, n);
return true;
}
bool nl_trailer_build(uint8_t out[NL_TRAILER_SIZE], const char *device, const char *version, const uint8_t sha256[32])
{
memset(out, 0xFF, NL_TRAILER_SIZE);
memcpy(&out[OFF_MAGIC], "NINL", 4);
out[OFF_VERSION] = NL_TRAILER_VERSION;
if (!copy_field(&out[OFF_DEVICE], device, NL_TRAILER_DEVICE_LEN) ||
!copy_field(&out[OFF_FW], version, NL_TRAILER_VERSION_LEN))
return false;
memcpy(&out[OFF_SHA], sha256, 32);
return true;
}
static bool terminated(const uint8_t *field, uint32_t len)
{
for (uint32_t i = 0; i < len; i++)
if (field[i] == 0)
return true;
return false;
}
nl_trailer_err_t nl_trailer_verify(const uint8_t *tail, uint32_t tail_len, const char *device, const uint8_t sha256[32])
{
if (tail == NULL || tail_len < NL_TRAILER_SIZE)
return NL_TRAILER_ERR_SIZE;
if (memcmp(&tail[OFF_MAGIC], "NINL", 4) != 0)
return NL_TRAILER_ERR_MAGIC;
if (tail[OFF_VERSION] != NL_TRAILER_VERSION)
return NL_TRAILER_ERR_VERSION;
if (!terminated(&tail[OFF_DEVICE], NL_TRAILER_DEVICE_LEN) ||
strcmp((const char *)&tail[OFF_DEVICE], device) != 0)
return NL_TRAILER_ERR_DEVICE;
if (memcmp(&tail[OFF_SHA], sha256, 32) != 0)
return NL_TRAILER_ERR_HASH;
return NL_TRAILER_OK;
}
void nl_trailer_version(const uint8_t *tail, char *dst)
{
memcpy(dst, &tail[OFF_FW], NL_TRAILER_VERSION_LEN);
dst[NL_TRAILER_VERSION_LEN - 1] = '\0';
}
const char *nl_trailer_err_name(nl_trailer_err_t e)
{
switch (e) {
case NL_TRAILER_ERR_DEVICE: return "device_mismatch";
case NL_TRAILER_ERR_HASH: return "hash";
case NL_TRAILER_OK: return NULL;
default: return "trailer";
}
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef NL_FWUP_TRAILER_H
#define NL_FWUP_TRAILER_H
#include <stdbool.h>
#include <stdint.h>
#define NL_TRAILER_SIZE 512u
#define NL_TRAILER_VERSION 1u
#define NL_TRAILER_DEVICE_LEN 16u
#define NL_TRAILER_VERSION_LEN 16u
typedef enum {
NL_TRAILER_OK = 0,
NL_TRAILER_ERR_SIZE,
NL_TRAILER_ERR_MAGIC,
NL_TRAILER_ERR_VERSION,
NL_TRAILER_ERR_DEVICE,
NL_TRAILER_ERR_HASH
} nl_trailer_err_t;
/* "NINL" | version | device[16] | fw_version[16] | sha256[32] | 0xFF padding */
bool nl_trailer_build(uint8_t out[NL_TRAILER_SIZE], const char *device, const char *version, const uint8_t sha256[32]);
nl_trailer_err_t nl_trailer_verify(const uint8_t *tail, uint32_t tail_len, const char *device, const uint8_t sha256[32]);
void nl_trailer_version(const uint8_t *tail, char *dst); /* dst: NL_TRAILER_VERSION_LEN bytes */
/* Maps to the last_ota_error vocabulary; NULL for NL_TRAILER_OK. */
const char *nl_trailer_err_name(nl_trailer_err_t e);
#endif