Skip to main content

Module ubft

Module ubft 

Source
Expand description

Ed25519 as the signature service of a uBFT replica (feature ubft).

§The problem

uBFT runs consensus entirely on an Alveo U280. On its slow path every replica signs a 64-bit summary of the slot, sends the signature to every peer, and verifies the shares it receives until it holds 2f + 1. It calls the Vitis Security Library’s Ed25519 inline, so the whole state machine stops for every signature and every verification. That signer is the routed design’s worst path (−2.866 ns), which pulls the kernel clock from 300 MHz down to 161.3 MHz. It also hashes only one byte of the summary: the calls pass a length of 1.

§The idea

UbftEd25519 is a service that sits next to uBFT on the chip. It takes one request at a time on a stream and answers in microseconds, with the same streams and header layout as DSig’s service (rhdl_dsig_scalable_core ubft), so uBFT picks a scheme at compile time with the same HLS stream calls. Inside are this crate’s cached-key signer and known-key verifier.

  uBFT ──sign request──▶ ┌────────────── UbftEd25519 ──────────────┐
       ◀──R‖S, tag────── │ Ed25519SignCore (cached key)            │
  uBFT ──verify request─▶│ KnownKeyVerifyCore, 16 trusted key slots│
       ◀──verdict word── └──── AXI4-Lite: seed, keys, counters ────┘
  • Signing. A request is one 64-byte beat: an 8-byte tag, then a 48-byte message (layout v2, ABI_VERSION 2). The signed message is those 48 bytes zero-extended to 64 bytes, an ordinary RFC 8032 signature that any Ed25519 library checks. rhdl_ubft puts a domain magic, a role, a session id and its (view, slot, k, m) there, so a share from another run or another role does not verify. (v1 signed bytes 0..16 and carried the tag at 16..24.) The answer is two beats: R‖S (the 64 bytes uBFT mails to its peers), then the tag.
  • Verifying. A request is three beats: a header (the signer’s key slot and a 32-bit tag), the 64-byte message as it was signed, and R‖S. The verdict word comes back with the slot and the tag.
  • Peers. One key per replica, so the verifier trusts up to KEY_SLOTS = 16 keys (N ≤ 17 replicas; uBFT has N ≤ 12).
  • Order. Answers can come back out of order. Match them by tag.

§Streams

PortDirectionBeatContent
s_axis_signin512 bitsbytes 0..8 tag (LE64), 8..56 message
m_axis_sigout512 bits, tlast on beat 1beat 0: R‖S; beat 1: bytes 0..8 tag
s_axis_verifyin512 bits, tlast on beat 2beat 0: byte 0 bits 0..4 key slot, bytes 4..8 tag (LE32); beat 1: message; beat 2: R‖S
m_axis_verdictout64 bitsbits 0..8 verdict, 8..12 key slot, 32..64 tag

A verdict of 0x80 means valid. Otherwise it is 0x80 | code, with a VERIFY_* code of crate::verify_core: 7 means the slot’s key is not loaded, 6 that the equation failed.

§Register map (32-bit words)

OffsetNameAccess
0x000AP_CTRL: bit 0 ap_start, 1 ap_done (clear on read), 2 ap_idle, 3 ap_readyRW
0x004/0x008/0x00cGIE / IER / ISRRW
0x010arg sign_count: signatures this sessionW
0x014arg verify_count: verifications this sessionW
0x050 + 4wargs seed0..seed7: the signer’s Ed25519 seed (secret)W
0x070arg key_mask: trusted key slots in use (bits 0..16)W
0x200MAGIC = MAGIC (“ESU1”)R
0x204ABI = ABI_VERSIONR
0x208SHAPE: fixed-base machines bits 0..8, verify machines 8..16, key slots 24..29R
0x20cFAULT: bit 0 signer, 2 verify core, 3 a trusted key rejected, 4 verify stream framingR
0x210/0x214TICKS lo (snapshots hi) / hiR
0x218/0x21cSTART_TICK lo/hiR
0x220/0x224DONE_TICK lo/hiR
0x228/0x22cKEY_TICK lo/hi: the signer’s key and the trusted keys are loadedR
0x230SIGNED: signatures sentR
0x234SIGN_TAKEN: sign requests acceptedR
0x238VERIFIED: verdicts sentR
0x23cVALID: verdicts that were 0x80R
0x250 + 4isign latency: N, LAST, MIN, MAX, SUM lo, SUM hiR
0x270 + 4iverify latency: same six wordsR
0x2a0 + 4wPUBLIC_KEY: the signer’s Ed25519 public key (8 × u32)R
0x400 + 0x20·s + 4wargs key{s}_{w}: slot s’s public key, bytes 4w..4w+4 LEW

The words up to 0x2c0 sit where DSig’s service has them. The trusted keys moved to 0x400: 16 slots at DSig’s 0x080 would run into the status words at 0x200.

§How latency is measured

As in DSig’s service: the kernel times isolated requests on its own clock, from the request’s first handshake to the answer’s last, when no other request of the same kind is in flight. Loaded latency is not measured here.

§Session rules

The host writes the seed, the keys, key_mask and the counts, then sets ap_start. The signer expands its seed and the loader puts each masked key into the verifier, about 105,000 cycles each. The sign stream opens once the signer’s key is cached and the verify stream once every masked slot has settled. The session is done when sign_count signatures and verify_count verdicts have left. The seed has no read path.

Structs§

AxiLiteIn
AXI4-Lite requests from the host (the layout of DSig’s AxiLiteIn, so both services use one Verilog wrapper).
AxiLiteOut
AXI4-Lite responses, every one from a register (the layout of DSig’s AxiLiteOut).
Axis64
One 64-bit stream beat (the verdict stream).
Axis512
One 512-bit stream beat (tvalid, tdata, tlast; tready travels the other way as a plain bool). The layout of DSig’s Axis512.
Latency
Isolated-request latency statistics, in cycles.
UbftEd25519
The uBFT Ed25519 service kernel: a signer with NFB fixed-base machines and a verifier with NV verify machines (one SHA-512 ring and one scalar ring each). uBFT signs once per consensus slot and verifies at most N − 1 shares, so UbftEd25519<1, 1> is the usual build.
UbftIn
Kernel inputs.
UbftOut
Kernel outputs.

Constants§

ABI_VERSION
Register-map version.
ARG_KEYS
key0_0; slot s, word w at + 0x20·s + 4w.
ARG_KEY_MASK
key_mask.
ARG_SEED
seed0.
ARG_SIGN_COUNT
sign_count.
ARG_VERIFY_COUNT
verify_count.
IN_FLIGHT
Requests of each kind the service holds at once (in a core or waiting on an output stream): the tag tables’ size.
MAGIC
MAGIC register value (“ESU1” in little-endian ASCII).
REG_ABI
ABI.
REG_DONE_TICK
DONE_TICK lo.
REG_FAULT
FAULT.
REG_KEY_TICK
KEY_TICK lo.
REG_MAGIC
MAGIC.
REG_PUBLIC_KEY
PUBLIC_KEY words.
REG_SHAPE
SHAPE.
REG_SIGNED
SIGNED.
REG_SIGN_LATENCY
Sign latency block (six words).
REG_SIGN_TAKEN
SIGN_TAKEN.
REG_START_TICK
START_TICK lo.
REG_TICKS
TICKS lo.
REG_VALID
VALID.
REG_VERIFIED
VERIFIED.
REG_VERIFY_LATENCY
Verify latency block (six words).

Functions§

beat_words
A beat’s bytes as eight little-endian words.
latency_kernel
Opens or closes a latency measurement (DSig’s rule): begin when a request is taken with none in flight, end when an answer’s last beat leaves with one in flight, abandon when a second request arrives.
latency_word
One register word of a latency block (i = 0 N, 1 LAST, 2 MIN, 3 MAX, 4 SUM lo, 5 SUM hi).
lowest_free
The lowest set bit of a tag table’s free mask (index 0 if none is set).
sign_message
The message a sign beat asks for, layout v2 (ABI 2): bytes 8..56 of the beat (words 1..7), zero-extended to 64 bytes. Bytes 0..8 are the tag and are not signed. The service signs exactly this; tests call it to get the same bytes.
ubft_ed25519_kernel
The kernel’s logic.
words_beat
Eight little-endian words as a beat’s bytes.