Files
MeowOS-For-R3P2/patch_v2/meow_verify/meow_sig.h
T

130 lines
5.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* meow_sig.h — .mpk 签名块格式(MPK_SIGNATURE_DESIGN §3.1,2B 扩展 §7)+ 被签消息构造。
*
* .mpk = [ tar.gz bytes ......................... ] [ meow_sig_block(变长 LE,v1/v2)]
*
* meow_sig_block v1(packed,总长 MEOW_SIG_BLOCK_LEN_V1=180):
* char magic[8]; "MEOWSIG1"
* uint8_t alg; 1 = ed25519
* uint8_t flags; 0
* uint16_t pad; (0)
* char package[64]; 权威包名(== app.json.package == 文件名茎)
* uint8_t payload_sha256[32];sha256(整个 .mpk 去掉尾部 footer 的其余字节)
* uint8_t sig[64]; Ed25519(pk, msg)
* uint32_t msg_len; 实际签名的 msg 字节数(LE)
* uint32_t block_len; 本块总长(LE;= MEOW_SIG_BLOCK_LEN_V1)
*
* meow_sig_block v2(packed,总长 MEOW_SIG_BLOCK_LEN_V2=184;2B 加固):
* 在 v1 的 sig 后、msg_len 前插入 uint32_t ts(unix 秒,LE,**纳入被签消息**)。
* 前 172 字节(magic/alg/flags/pad/package/payload_sha256/sig)与 v1 完全同偏移,
* 故验签端可据尾部 block_len(v1=180 / v2=184)判别版本后按偏移取字段。
* flags bit0 (MEOW_SIG_FLAG_TS)=1 标记含时间戳。
*
* 被签消息:
* v1 msg = "MEOWSIG1" || alg(1B) || package_len(4B,LE) || package || payload_sha256(32B)。
* v2 msg = v1 msg || ts(4B,LE)。 — 时间戳被签名绑定,防改时间戳。
*
* 本文件由 meow_verify 与 meow_sign 共用(meow_sign 用相对路径 include)。
* v1/v2 兼容:验签端读 v1(旧 2A 包)不检时间戳(无该字段),读 v2(2B 包)检 ts 未来宽限。
* (明确不做:防重放/过期——ts 只做「未来异常」宽限拒绝,见 MPK_SIGNATURE_DESIGN §8 诚实标注。) */
#ifndef MEOW_SIG_H
#define MEOW_SIG_H
#include <stdint.h>
#include <string.h>
#define MEOW_SIG_MAGIC "MEOWSIG1"
#define MEOW_SIG_MAGIC_LEN 8
#define MEOW_SIG_ALG_ED25519 1
#define MEOW_SIG_PKG_MAX 64
#define MEOW_SIG_SHA256_LEN 32
#define MEOW_SIG_SIG_LEN 64
/* flags 位(v2) */
#define MEOW_SIG_FLAG_TS 0x01u /* 含签名时间戳(v2) */
typedef struct __attribute__((packed)) {
uint8_t magic[MEOW_SIG_MAGIC_LEN];
uint8_t alg;
uint8_t flags;
uint16_t pad;
char package[MEOW_SIG_PKG_MAX];
uint8_t payload_sha256[MEOW_SIG_SHA256_LEN];
uint8_t sig[MEOW_SIG_SIG_LEN];
uint32_t msg_len;
uint32_t block_len;
} meow_sig_block_t;
typedef struct __attribute__((packed)) {
uint8_t magic[MEOW_SIG_MAGIC_LEN];
uint8_t alg;
uint8_t flags;
uint16_t pad;
char package[MEOW_SIG_PKG_MAX];
uint8_t payload_sha256[MEOW_SIG_SHA256_LEN];
uint8_t sig[MEOW_SIG_SIG_LEN];
uint32_t ts; /* v2: unix 时间戳(LE,被签名) */
uint32_t msg_len;
uint32_t block_len;
} meow_sig_block_v2_t;
/* 块版本:由尾部 block_len 判别(v1=180 无 ts;v2=184 含 ts) */
#define MEOW_SIG_BLOCK_LEN_V1 (sizeof(meow_sig_block_t)) /* 180 */
#define MEOW_SIG_BLOCK_LEN_V2 (sizeof(meow_sig_block_v2_t)) /* 184 = 180 + ts(4) */
#define MEOW_SIG_BLOCK_MAX MEOW_SIG_BLOCK_LEN_V2
/* 签名时间戳未来宽限(秒):ts 在 now+宽限内视为合法时钟误差,超出即拒。 */
#define MEOW_SIG_TS_GRACE 86400u /* 24h */
/* 字段偏移(前 172B 两版同偏移;ts/msg_len 因版本异,见下)。 */
#define MEOW_SIG_OFF_PKG 12
#define MEOW_SIG_OFF_SHA 76
#define MEOW_SIG_OFF_SIG 108
#define MEOW_SIG_OFF_TS 172 /* v2 only */
#define MEOW_SIG_OFF_MSGLEN_V1 (MEOW_SIG_BLOCK_LEN_V1 - 8) /* 172 */
#define MEOW_SIG_OFF_MSGLEN_V2 (MEOW_SIG_BLOCK_LEN_V2 - 8) /* 176 */
/* 按字节读取 LE 的 uint32(避免 packed 解引用对齐告警) */
static inline uint32_t meow_le32(const uint8_t *p)
{
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) |
((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
}
static inline void meow_le32_put(uint8_t *p, uint32_t v)
{
p[0] = (uint8_t)(v & 0xff);
p[1] = (uint8_t)((v >> 8) & 0xff);
p[2] = (uint8_t)((v >> 16) & 0xff);
p[3] = (uint8_t)((v >> 24) & 0xff);
}
/* v1 或 v2 的 msg 均不超过此上限(v1 109 / v2 113)。 */
#define MEOW_SIG_MSG_MAX (MEOW_SIG_MAGIC_LEN + 1 + 4 + MEOW_SIG_PKG_MAX + MEOW_SIG_SHA256_LEN + 4)
/* 按设计构造 v1 被签消息 msg = "MEOWSIG1" || alg(1B) || package_len(4B,LE) || package || payload_sha256(32B)。
* 返回 msg 字节数。签名端与验签端必须用同一构造(meow_sign / meow_verify 共用)。 */
static inline unsigned meow_sig_msg_build(char *out, const char *package,
const uint8_t payload_sha256[MEOW_SIG_SHA256_LEN])
{
unsigned pkg_len = (unsigned)strlen(package);
if (pkg_len > MEOW_SIG_PKG_MAX) pkg_len = MEOW_SIG_PKG_MAX;
unsigned o = 0;
memcpy(out + o, MEOW_SIG_MAGIC, MEOW_SIG_MAGIC_LEN); o += MEOW_SIG_MAGIC_LEN;
out[o++] = MEOW_SIG_ALG_ED25519;
meow_le32_put((uint8_t *)out + o, (uint32_t)pkg_len); o += 4;
memcpy(out + o, package, pkg_len); o += pkg_len;
memcpy(out + o, payload_sha256, MEOW_SIG_SHA256_LEN); o += MEOW_SIG_SHA256_LEN;
return o;
}
/* 构造 v2 被签消息 = v1 msg || ts(4B,LE)。返回 msg 字节数(= v1 msg + 4)。 */
static inline unsigned meow_sig_msg_build_v2(char *out, const char *package,
const uint8_t payload_sha256[MEOW_SIG_SHA256_LEN],
uint32_t ts)
{
unsigned o = meow_sig_msg_build(out, package, payload_sha256);
meow_le32_put((uint8_t *)out + o, ts); o += 4;
return o;
}
#endif /* MEOW_SIG_H */