Ground-Zerro / HydraRoute Public
Code Issues Pull requests Actions Releases View on GitHub ↗
2.1 KB c
#ifndef CRYPTO_ASM_H
#define CRYPTO_ASM_H

#include <stdint.h>
#include <stddef.h>
#include <string.h>

#define CRYPTO_ASM_RANGES 8

typedef struct {
    uint16_t lo, hi;
} asm_range_t;

typedef struct {
    uint8_t    *buf;
    uint16_t    cap;
    uint16_t    total;
    uint8_t     nranges;
    uint8_t     broken;
    asm_range_t r[CRYPTO_ASM_RANGES];
} crypto_asm_t;

static inline void asm_reset(crypto_asm_t *a) {
    a->total = 0;
    a->nranges = 0;
    a->broken = 0;
}

static inline int asm_mark(crypto_asm_t *a, uint16_t lo, uint16_t hi) {
    asm_range_t out[CRYPTO_ASM_RANGES + 1];
    uint8_t i = 0, w = 0;
    while (i < a->nranges && a->r[i].hi < lo) out[w++] = a->r[i++];
    while (i < a->nranges && a->r[i].lo <= hi) {
        if (a->r[i].lo < lo) lo = a->r[i].lo;
        if (a->r[i].hi > hi) hi = a->r[i].hi;
        i++;
    }
    out[w++] = (asm_range_t){ lo, hi };
    while (i < a->nranges) out[w++] = a->r[i++];
    if (w > CRYPTO_ASM_RANGES) return -1;
    memcpy(a->r, out, w * sizeof(out[0]));
    a->nranges = w;
    return 0;
}

static inline void asm_put(crypto_asm_t *a, uint64_t off, const uint8_t *p, size_t len) {
    if (a->broken || len == 0 || off >= a->cap) return;
    if (len > a->cap - off) len = a->cap - (size_t)off;
    memcpy(a->buf + off, p, len);
    if (asm_mark(a, (uint16_t)off, (uint16_t)(off + len)) != 0) a->broken = 1;
}

static inline void asm_merge(crypto_asm_t *dst, const crypto_asm_t *src) {
    for (uint8_t i = 0; i < src->nranges; i++)
        asm_put(dst, src->r[i].lo, src->buf + src->r[i].lo,
                (size_t)(src->r[i].hi - src->r[i].lo));
    if (src->broken) dst->broken = 1;
}

static inline int asm_complete(const crypto_asm_t *a) {
    return !a->broken && a->total && a->nranges &&
           a->r[0].lo == 0 && a->r[0].hi >= a->total;
}

static inline void asm_handshake_total(crypto_asm_t *a) {
    if (a->total || !a->nranges || a->r[0].lo != 0 || a->r[0].hi < 4) return;
    uint32_t t = 4 + ((uint32_t)a->buf[1] << 16 | (uint32_t)a->buf[2] << 8 | a->buf[3]);
    if (t > a->cap) a->broken = 1;
    else a->total = (uint16_t)t;
}

#endif