Skip to content
VLSI Mentor

CXL · Module 19

Device Authentication

Every chapter so far assumed the device is what it claims. This chapter builds measurement against a golden value, nonce freshness, certificate chains, revocation, trust models, authentication ordering, failure policy, cost amortisation and re-authentication.

Eighteen chapters of this track have assumed something none of them stated: that the device on the other end of the link is the device it says it is.

15.3 discovered devices and believed what they reported. 17.1 built an expander whose entire self-description is a claim. 15.4 bound one to a host address range, which is the moment a device gains the ability to read and write host memory.

This chapter is the check that belongs before that moment.

1. The Engineering Problem — A Claim Is Not An Identity

Six things stand between "the device responded" and "the device is trusted".

A measurement is a hash of what the device is running, and it means nothing without a known-good value to compare it against. A verifier with no golden value can only accept. Section 5.

A challenge must be fresh. A signature over a nonce that has been used before is a recording, and a recording proves the device was there once, not that it is there now. Section 6.

A certificate chain is only as strong as its weakest link, and the link most often skipped is the intermediate — the one an attacker with a mis-issued certificate uses. Section 7.

Revocation is a separate check from validity. A certificate can verify perfectly and still be one the issuer has withdrawn, and a verifier that never consults the list will accept it forever. Section 9.

When authentication happens decides what it protects. Authenticating after a device has been bound to host memory protects nothing that matters. Section 11.

And what happens on failure is a policy — refusing, admitting at reduced privilege, or admitting anyway. Not choosing means admitting anyway. Section 12.

This chapter against 17.4, stated precisely. That one asks is this device good enough to deploy. This one asks is this device the one I evaluated.

2. The One-Sentence Model

Authentication answers which device this is and what it is running, and every step of it is a comparison against something the verifier already knew — every defect below is a comparison that was skipped or had nothing to compare against.

3. What This Chapter Owns

GroundOwner
Discovering that a device exists15.3
Binding a device to a host15.4
Evaluating whether a device is good enough17.4
Protecting the data on the link19.2
Establishing which device this isthis chapter

Deferred:

Deferred groundOwner
Integrity and confidentiality of traffic19.2
Isolating hosts and tenants that share a pool19.3
Policy enforcement across many tenants19.4
The cryptographic primitives themselvesout of scope — see §4

4. Teaching-Model Boundary

Sixteen-bit identities, a three-link chain and a single revoked identifier are far smaller than any real deployment. They are sized so every boundary is reachable and every result checkable by hand.

What is not simplified is the structure: a measurement compared against a golden value, a nonce compared against the last one used, a chain whose links are checked independently, a revocation list consulted separately from signature validity, an ordering that gates binding on authentication, and a failure policy with three outcomes rather than two.

Three things are absent by design. Cryptography is entirely out of scope — signature verification, hash construction and key exchange are inputs to these models, and a chapter that modelled them badly would be worse than one that does not model them at all. There is no key-management model: where the golden values and the root come from is a provisioning problem. And 19.2 owns the link itself — this chapter establishes identity and says nothing about protecting the traffic that follows.

5. RTL 1 — A Measurement Needs Something To Compare Against

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// A measurement is a hash of what the device is running. Comparing it against a
// known-good value is the whole of attestation.
module measurement_check #(parameter int TRUST_REPORTED = 0) (
  input  logic clk, rst_n,
  input  logic        verify,
  input  logic [15:0] reported, golden,
  input  logic        golden_known,
  output logic        measurement_ok, accepted,
  output logic [7:0]  n_verify, n_rejected,
  output logic        blind_accept_err
);
  assign measurement_ok = golden_known && (reported == golden);
  // The trusting build accepts whatever the device reports, which is what a
  // verifier does when it has no golden value to compare against.
  assign accepted = (TRUST_REPORTED != 0) ? 1'b1 : measurement_ok;
  // Accepting a measurement that was never compared against anything.
  assign blind_accept_err = verify && accepted && !measurement_ok;
  // ... verification counters omitted for length
endmodule

Three verifications:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  measure: verified=3 rejected=2 | trusting rejected=0 blind=2
CaseWhat each verifier does
The measurement matches the golden valuecorrect: accept · trusting: accept
A different measurementcorrect: reject · trusting: accept, blindly
No golden value at allcorrect: reject · trusting: accept, blindly

The third row is the one that matters most and the one most systems are in. A verifier that has never been provisioned with a known-good measurement cannot distinguish good firmware from bad, and the honest response is to refuse rather than to accept. golden_known is a term in the conjunction for exactly that reason.

6. RTL 2 — A Challenge Must Be Fresh

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// A challenge must be fresh, or a recorded response answers it forever.
module challenge_freshness #(parameter int STATIC_NONCE = 0) (
  input  logic clk, rst_n,
  input  logic        challenge,
  input  logic [15:0] nonce_in, last_nonce,
  input  logic        sig_valid,
  output logic [15:0] nonce_used,
  output logic        fresh, accepted,
  output logic [7:0]  n_challenges, n_replays,
  output logic        replay_err
);
  // The static build reuses one nonce, so any recorded response is valid again.
  assign nonce_used = (STATIC_NONCE != 0) ? 16'hA5A5 : nonce_in;
  assign fresh      = (nonce_used != last_nonce);
  assign accepted   = sig_valid && fresh;
  // Accepting a signature over a nonce that has been used before.
  assign replay_err = challenge && sig_valid && !fresh;
  // ... challenge counters omitted for length
endmodule

Seven challenges, three of them against a verifier that reuses one nonce:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  fresh: challenges=7 replays=2 | static-nonce replays=3

The static-nonce build issues the same challenge three times and a single recorded response answers all three. That is the whole of a replay attack against attestation: the device was genuine once, somebody kept the answer, and the verifier cannot tell the recording from the device.

replay_err requires the signature to be valid. An invalid signature over a stale nonce is not a replay — it is an ordinary failure, and the bench drives that case explicitly:

Signature and nonceThe verdict
validfresh · accepted
validstale · refused — a replay
invalidfresh · refused — an ordinary failure
invalidstale · refused — still not a replay

The fourth row is what makes the checker mean something. A replay is a successful response to a challenge that has been asked before; reporting one on every failed signature turns the metric into a failure count.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// A certificate chain is only as good as the root it terminates at, and only if
// every link is checked.
module cert_chain #(parameter int SKIP_INTERMEDIATE = 0) (
  input  logic clk, rst_n,
  input  logic       validate,
  input  logic       leaf_ok, intermediate_ok, root_trusted,
  input  logic [1:0] depth,
  output logic       chain_valid,
  output logic [2:0] fail_mask,
  output logic [7:0] n_chains, n_bad,
  output logic       unchecked_link_err
);
  assign fail_mask[0] = ~leaf_ok;
  assign fail_mask[1] = ~intermediate_ok;
  assign fail_mask[2] = ~root_trusted;
  // The skipping build checks the leaf and the root and takes the middle on
  // faith, which is the link an attacker with a mis-issued certificate uses.
  assign chain_valid = (SKIP_INTERMEDIATE != 0) ? (leaf_ok && root_trusted)
                                                : (fail_mask == 3'd0);
  // Declaring a chain valid with a link unverified.
  assign unchecked_link_err = validate && chain_valid && (fail_mask != 3'd0);
  // ... chain counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  chain: validations=4 bad=3 | skipping bad=2 unchecked=1

The skipping build finds two of the three bad chains. It catches a bad leaf and an untrusted root — the two ends — and misses the middle entirely. That is not a random omission: the leaf and the root are the two links a verifier naturally has in hand, and the intermediate is the one that requires an extra fetch.

Each of the three links is falsified alone, and the failure mask names which one. 3'b010 sends somebody to the intermediate; a single "chain invalid" bit sends them to all three.

8. Waveform — An Authentication Exchange

Transcribed from the printed trace. One stimulus stream, both builds.

An eight-cycle waveform of an authentication exchange. A nonce is issued, the device responds with a signature and a measurement, the certificate chain is fetched and validated, the revocation list is consulted, and only then is the device authenticated and permitted to bind. A second trace shows a signature-only verifier authenticating at the response and permitting a bind four cycles earlier.response receivedresponse receivedsignature-only binds heresignature-only binds hereall five gates passall five gates passbind permittedbind permittedclkstepnoncerespchainrevokemeasokbindservesig_okfreshchain_oknot_revkmeas_okauthedsig_onlyt0t1t2t3t4t5t6t7
Figure 1 — The authed row goes high at cycle 4, when the last of five gates passes. The sig_only row goes high at cycle 1, on the signature alone — three cycles before the chain is validated, four before the revocation list is consulted and before the measurement has been compared against anything.

The sig_only row is not a strawman of a broken implementation. A valid signature genuinely proves the device holds a private key — it proves nothing about which key, whether that key's certificate is still valid, or what firmware the device is running. Three separate questions, and the signature answers none of them.

9. RTL 4 — Revocation Is A Separate Question

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Revocation: a certificate that was valid yesterday may not be today, and a
// verifier that never checks will accept it forever.
module revocation #(parameter int NO_REVOCATION_CHECK = 0) (
  input  logic clk, rst_n,
  input  logic        check,
  input  logic [15:0] cert_id, revoked_id,
  input  logic        list_fresh, sig_ok,
  output logic        revoked, stale_list, accepted,
  output logic [7:0]  n_checks, n_revoked,
  output logic        revoked_accept_err
);
  assign revoked    = (cert_id == revoked_id);
  assign stale_list = ~list_fresh;
  // The skipping build validates the signature and never consults the list.
  assign accepted = (NO_REVOCATION_CHECK != 0) ? sig_ok
                                                : (sig_ok && !revoked && list_fresh);
  // Accepting a certificate that appears on the revocation list.
  assign revoked_accept_err = check && accepted && revoked;
  // ... check counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  revoke: checks=4 revoked=1 | skipping accepted revoked=1

Four checks, and the third is the interesting one:

Certificate, signature and listWhat the correct verifier does
not revoked, valid signature, fresh listaccept
revoked, valid signature, fresh listrefuse
not revoked, valid signature, stale listrefuse — it cannot know
not revoked, invalid signature, fresh listrefuse

A stale revocation list is a refusal, not a pass. A verifier whose list is out of date does not know whether the certificate in front of it has been withdrawn, and treating "I could not check" as "it checked out" is the failure mode that makes revocation infrastructure pointless.

The acceptance is a three-term conjunction and each term is falsified alone. The two mutations that drop either the revocation term or the freshness term individually are killed by different rows of that table.

10. RTL 5 — Trust On First Use Against A Root

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Trust on first use records what it saw; a PKI checks against what it was told.
// They fail differently and only one of them notices a swap.
module trust_model #(parameter int TOFU = 0) (
  input  logic clk, rst_n,
  input  logic        attach,
  input  logic [15:0] presented_id, pinned_id, root_signed_id,
  input  logic        first_attach, root_ok,
  output logic        trusted, pinned_match, root_match,
  output logic [7:0]  n_attach, n_refused,
  output logic        swap_missed_err
);
  assign pinned_match = (presented_id == pinned_id);
  assign root_match   = root_ok && (presented_id == root_signed_id);
  // Trust on first use accepts anything the first time and pins it. A PKI checks
  // every attach against the root, including the first.
  assign trusted = (TOFU != 0) ? (first_attach || pinned_match) : root_match;
  // A device swapped for one the root never signed, accepted anyway.
  assign swap_missed_err = attach && trusted && !root_match;
  // ... attach counters omitted for length
endmodule

Six attaches:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  trust: attaches=6 refused=3 | tofu refused=1 swaps missed=2
AttachWhat the PKI build does, and trust-on-first-use
First attach, root signed ittrust · trust — and pin it
Later attach, same devicetrust · trust
Swapped device, same pinned id, root did not sign itrefuse · trust — the swap is missed
Identity matching neither pin nor rootrefuse · refuse
Root itself did not verifyrefuse · trust — also missed
A new device the root signedtrust · trust

Trust on first use missed two of the three cases the PKI build caught, and the two it missed are the two that matter: a swapped device presenting a pinned identity, and a case where the root itself did not verify.

The trade is real rather than one-sided. Trust on first use needs no provisioning and no root; a PKI needs both, and a PKI whose root is compromised trusts everything the root signs. The failure modes are different, and choosing between them requires knowing which one your deployment can detect.

root_match requires root_ok and an identity match, and the fifth row proves the term earns its place: an identity that matches what the root would have signed proves nothing if the root's own signature did not verify.

11. RTL 6 — When Authentication Happens

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// When authentication happens decides what it protects. Authenticating after the
// device has been given memory protects nothing.
module auth_ordering #(parameter int AUTH_AFTER_USE = 0) (
  input  logic clk, rst_n,
  input  logic       step,
  input  logic [2:0] phase,        // 0 link up, 1 enumerate, 2 authenticate, 3 bind, 4 in use
  input  logic       authenticated,
  output logic       may_bind, may_serve,
  output logic [7:0] n_steps, n_unauth_binds,
  output logic       premature_bind_err
);
  // Binding a device to a host address range is the point of no return: after
  // it, the device can read and write host memory.
  assign may_bind  = (AUTH_AFTER_USE != 0) ? (phase >= 3'd3)
                                           : (authenticated && (phase >= 3'd3));
  assign may_serve = may_bind && (phase >= 3'd4);
  // Binding a device that has not been authenticated.
  assign premature_bind_err = step && may_bind && !authenticated;
  // ... step counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  ordering: steps=6 unauth_binds=0 | after-use unauth_binds=2

Binding is the point of no return. 15.4 established that binding attaches a device to a host address range; from that moment the device can read and write host memory. Everything before it is reversible and everything after it is not.

The phases and where the gate sits:

PhaseMay it bind, and why
Link upno · nothing is known about the device yet
Enumerateno · it has described itself, and the description is a claim
Authenticateno — not even here · the exchange is in progress
Bindyes, if authenticated · the gate
In useyes — and may serve

The after-use build binds at the same phase without the authentication term, and its two premature binds are two devices given host memory on the strength of their own self-description.

12. RTL 7 — What Happens On Failure

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// What a verifier does when authentication fails. Refusing is a policy choice
// and so is continuing; not choosing is not.
module failure_policy #(parameter int FAIL_OPEN = 0) (
  input  logic clk, rst_n,
  input  logic       result,
  input  logic       auth_ok, degraded_mode_available,
  output logic       admit, admit_degraded, refuse,
  output logic [7:0] n_results, n_admitted, n_refused,
  output logic       fail_open_err
);
  // Fail-closed refuses. Fail-open admits, which is what a system does when the
  // policy was never written down.
  assign admit          = (FAIL_OPEN != 0) ? 1'b1 : auth_ok;
  assign admit_degraded = !auth_ok && degraded_mode_available && (FAIL_OPEN == 0);
  assign refuse         = !admit && !admit_degraded;
  // Admitting a device at full privilege after authentication failed.
  assign fail_open_err = result && admit && !auth_ok;
  // ... result counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  policy: results=3 admitted=1 refused=1 | fail-open admitted=3

Three outcomes, not two. A failed authentication can be refused outright, or admitted at reduced privilege where the deployment has somewhere to put it:

Authentication and degraded modeThe outcome
succeededadmit at full privilege
failedavailable · admit degraded
failednone · refuse

The degraded path is what makes this a policy rather than a switch. A device that fails attestation might still be usable for something — the question is whether the deployment has a reduced-privilege mode to put it in, and that is a design decision made long before the failure.

The fail-open build admitted all three at full privilege, including both failures. It is the honest model of a system where nobody wrote the policy down: the code path that handles a failure does not exist, so the failure falls through.

A sequence diagram with three lifelines: host, device and a trust store. The host sends a nonce to the device, which returns a signed response with a measurement. The host fetches the certificate chain from the device, then checks the chain and the revocation list against the trust store, then compares the measurement against a golden value from the trust store. Only after all of that does the host bind the device.hostdevicetrust storefresh noncesigned response +measurementget certificatechainleaf, intermediate,rootchain to a trustedroot?and not revokedgolden measurement?compare — then bind
Figure 2 — Four of the eight messages go to the trust store, not to the device. Everything the device says is a claim; the checking happens against something the host obtained independently, which is why a verifier with no trust store can complete the exchange and verify nothing.

13. RTL 8 — What Authentication Costs

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Authentication costs time, and where it sits decides whether that time is on
// the critical path.
module auth_cost #(parameter int PER_ACCESS = 0) (
  input  logic clk, rst_n,
  input  logic        access,
  input  logic [15:0] auth_ns, access_ns, accesses,
  output logic [31:0] total_ns, amortised_ns,
  output logic [15:0] this_ns,
  output logic [7:0]  auth_share_pct,
  output logic        on_critical_path, per_access_err
);
  logic [31:0] am_q, sh_q;
  // Authenticating once at attach amortises over every access. Authenticating
  // per access puts the whole cost on every one of them.
  assign this_ns = (PER_ACCESS != 0) ? (auth_ns + access_ns) : access_ns;
  // ... amortisation omitted for length
  assign on_critical_path = (auth_share_pct > 8'd10);
  // Charging the authentication cost on an access that should not carry it.
  assign per_access_err = access && (this_ns > access_ns);
  // ... total omitted for length
endmodule

A 50 µs authentication against 300 ns accesses:

Accesses after attachCost per access and Auth share
150,300 ns · 99%
1000350 ns · 14% — still on the critical path
1470334 ns · exactly 10% — and off it
10,000305 ns · 1%
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  cost: amortised=50300ns share=99% critical=1 | per-access charges=5

Authentication is cheap because it happens once. The per-access build charges 50,300 ns on every access — 251,500 ns across five accesses against the correct build's 1,500 — which is why nobody authenticates per access and why the ordering of section 11 matters more than the cost.

This is 18.3 section 7's amortisation argument in a third setting, and the break-even was constructed rather than approached: 1470 accesses is the only count at which the share is exactly 10%.

14. RTL 9 — Trust Has An Expiry

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Re-authentication: a device authenticated once stays trusted until something
// says otherwise, and how long that is is a policy.
module reauth #(parameter int AUTH_ONCE = 0) (
  input  logic clk, rst_n,
  input  logic        tick, link_reset, fw_update,
  input  logic [15:0] since_auth, max_age,
  output logic        must_reauth, stale_trust,
  output logic [7:0]  n_ticks, n_reauth,
  output logic        stale_trust_err
);
  logic aged, event_seen;
  assign aged       = (since_auth >= max_age);
  assign event_seen = link_reset || fw_update;
  // The once-only build never re-authenticates, so trust established at attach
  // survives a firmware update the verifier never saw.
  assign must_reauth = (AUTH_ONCE != 0) ? 1'b0 : (aged || event_seen);
  assign stale_trust = (aged || event_seen) && !must_reauth;
  // Continuing to trust a device past the point the policy says to re-check.
  assign stale_trust_err = tick && stale_trust;
  // ... tick counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  reauth: ticks=5 required=3 | once-only required=0 stale=3

Three separate triggers, each driven alone:

TriggerWhy it invalidates the earlier result
Agethe measurement was of firmware running then, not now
Link resetthe device on the other end may not be the same device
A firmware updatethe measurement is definitively stale

The firmware-update case is the sharpest. Section 5's measurement was a hash of what the device was running at attach. After an update it is a hash of software that is no longer there, and the once-only build carries on trusting it — which means the attestation now certifies firmware that has been replaced.

The age comparison is inclusive and driven exactly: at the maximum age re-authentication is required; one below it is not.

A state machine showing the trust lifecycle of a device. From unknown, a successful authentication reaches trusted, where the device may be bound and served. Age, a link reset or a firmware update move it to expired, from which a re-authentication returns it to trusted and a failure returns it to unknown. A self-loop on trusted represents ordinary service while the trust is current.UNKNOWNTRUSTEDEXPIREDREFUSEDfive gates passfive gates passany gate failsany gatefailsservingservingage, reset or updateage, reset or updatere-authenticatedre-authenticatedre-auth failsre-auth fails
Figure 3 — The EXPIRED state is what the once-only build does not have. Without it TRUSTED has no exit, and the self-loop labelled “serving” runs forever on an attestation that may certify firmware replaced months ago.

The path from EXPIRED back to TRUSTED is what makes the expiry affordable. A device whose trust has aged out is not refused — it is re-checked, and section 13's amortisation is what makes that cheap enough to do. The two models are a pair: without the cost analysis, an expiry policy looks unaffordable; without the expiry, the cost analysis is measuring something that only ever happens once.

15. RTL 10 — Device Authentication Assembled

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Device authentication assembled: every gate a device must pass before a host
// binds memory to it.
module device_auth #(parameter int SIGNATURE_ONLY = 0) (
  input  logic clk, rst_n,
  input  logic       evaluate,
  input  logic       signature_valid,  // the response verifies
  input  logic       nonce_fresh,      // it answers this challenge
  input  logic       chain_valid,      // every link to the root checks
  input  logic       not_revoked,      // and none of them is revoked
  input  logic       measurement_ok,   // the firmware is what it should be
  output logic       authenticated,
  output logic [4:0] fail_mask,
  output logic [7:0] n_eval, n_authed,
  output logic       weak_auth_err
);
  assign fail_mask[0] = ~signature_valid;
  assign fail_mask[1] = ~nonce_fresh;
  assign fail_mask[2] = ~chain_valid;
  assign fail_mask[3] = ~not_revoked;
  assign fail_mask[4] = ~measurement_ok;
  // The signature-only build checks that the response verifies and stops, which
  // proves the device holds a key and nothing about which key or what it runs.
  assign authenticated = (SIGNATURE_ONLY != 0) ? signature_valid
                                                : (fail_mask == 5'd0);
  assign weak_auth_err = evaluate && authenticated && (fail_mask != 5'd0);
  // ... evaluation counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  auth: evaluated=6 authenticated=1 | signature-only authenticated=5

One authenticated device out of six, and the signature-only build authenticated five. Its four extra are freshness, chain, revocation and measurement — and each of them answers a question the signature does not:

GateThe question it answers and Signature-only
Signature validdoes it hold a private key? · caught
Nonce freshis it answering this challenge? · missed
Chain validis that key one we trust? · missed
Not revokedis that trust still current? · missed
Measurement okwhat is it running? · missed

A valid signature is a necessary condition and nothing more. It is satisfied by a recording (freshness), by a device with a legitimate key from an untrusted issuer (chain), by one whose certificate was withdrawn (revocation), and by genuine hardware running firmware nobody approved (measurement).

A flowchart of the five gates a device must pass before a host binds memory to it. A device responds to a challenge, then is checked in turn for whether the signature verifies, whether the nonce was fresh, whether the certificate chain reaches a trusted root, whether the certificate is unrevoked, and whether the measurement matches a golden value. Passing all five authenticates the device. Failing any one refuses it, and the failure mask names which gate failed.yesyesyesyesyesnoa device respondssignatureverifies?nonce fresh?chain reaches theroot?not revoked?measurementmatches?authenticated — maybindrefused — the mask sayswhy
Figure 4 — Five gates, five refusal paths. Only the first is about the signature; the other four are about which key, whether that key is still trusted, and what the device is running — three questions a valid signature cannot answer.

16. Quantitative Reasoning

Every number is from a printed line above. None describes any implementation.

Measurement. Three verifications, two rejected — one for a mismatch and one for having no golden value. The trusting build rejected zero.

Freshness. Seven challenges. The static-nonce build replayed three times on a single recorded response.

Chain. Four validations, three bad. The skipping build found two — both ends, missing the middle.

Revocation. Four checks, one revoked certificate accepted by the skipping build. A stale list is a refusal, not a pass.

Trust model. Six attaches: the PKI build refused three, trust-on-first-use refused one and missed two swaps.

Ordering. Six steps, two unauthenticated binds by the after-use build — two devices given host memory on their own say-so.

Failure policy. Three results: one admitted, one degraded, one refused. The fail-open build admitted all three at full privilege.

Cost. 50 µs of authentication is 99% of a single access and 1% across ten thousand. The break-even at 10% is exactly 1470 accesses.

Re-authentication. Five ticks, three required — age, link reset and firmware update. The once-only build required none.

Assembled. Six evaluations, one authenticated against the signature-only build's five.

17. Assertions

Every property is an immediate check written as cond !== 1'b1, sampled after a settle. 193 assertion sites across two testbenches.

# · modelProperty
1 · measureThe reported measurement matches the golden value
2 · measureSo it is accepted
3 · measureWith no blind acceptance
4 · measureIn either build
5 · measureA different measurement does not match
6 · measureSo the correct verifier refuses it
7 · measureThe trusting build accepts it
8 · measureWhich is a blind acceptance
9 · measureAnd the correct build makes none
10 · measureWith no golden value there is no match
11 · measureSo the correct verifier refuses
12 · measureThe trusting build accepts anyway
13 · measureBlindly
14 · measureThree verifications
15 · measureTwo of them rejected
16 · measureThe trusting build rejected none
17 · measureThe correct verifier never accepts blindly
18 · measureThe trusting build did twice
19 · freshA new nonce is fresh
20 · freshSo a valid signature is accepted
21 · freshWith no replay
22 · freshThe same nonce is not fresh
23 · freshSo the correct verifier refuses
24 · freshAnd reports a replay
25 · freshA fresh nonce is fresh for the correct build
26 · freshBut the static build reuses its own
27 · freshWhich is a replay
28 · freshAnd the correct build reports none
29 · freshA second fresh nonce is still fresh
30 · freshAnd the static build replays again
31 · freshA third is fresh too
32 · freshAnd the static build replays a third time
33 · freshThe nonce is fresh
34 · freshBut an invalid signature is refused
35 · freshAnd is not a replay
36 · freshIn either build
37 · freshThe nonce is stale
38 · freshBut an invalid signature over it is not a replay
39 · freshIn either build
40 · freshSeven challenges
41 · freshTwo stale nonces in the correct build
42 · freshThree in the static build
43 · freshThe correct build reported the one replay
44 · freshThe static build reported one on every reused challenge
45 · chainAll three links check
46 · chainSo the chain is valid
47 · chainWith no unchecked link
48 · chainThe intermediate alone is bad
49 · chainSo the correct chain is invalid
50 · chainThe skipping build calls it valid
51 · chainWhich is an unchecked link
52 · chainAnd the correct build reports none
53 · chainThe leaf alone, seen by both
54 · chainThe root alone, seen by both
55 · chainFour chain validations
56 · chainThree of them bad
57 · chainThe skipping build found two
58 · chainThe correct build never leaves a link unchecked
59 · chainThe skipping build did once
60 · revokeThis certificate is not on the list
61 · revokeSo it is accepted
62 · revokeWith no revoked acceptance
63 · revokeThis one is revoked
64 · revokeSo the correct verifier refuses
65 · revokeThe skipping build accepts it
66 · revokeWhich is accepting a revoked certificate
67 · revokeAnd the correct build does not
68 · revokeThe list is stale
69 · revokeSo the correct verifier refuses
70 · revokeThe skipping build never looks at the list
71 · revokeAnd this one is not revoked, so it is not that error
72 · revokeAn invalid signature is refused
73 · revokeIn both builds
74 · revokeFour revocation checks
75 · revokeOne revoked certificate
76 · revokeThe correct verifier never accepts a revoked certificate
77 · revokeThe skipping build did once
78 · trustThe root signed this identity
79 · trustSo the PKI build trusts it
80 · trustAnd so does trust-on-first-use
81 · trustWith nothing missed
82 · trustA later attach of the same device is still trusted
83 · trustBy both builds
84 · trustThe presented id still matches what was pinned
85 · trustBut the root did not sign it
86 · trustSo the PKI build refuses
87 · trustTrust-on-first-use accepts it
88 · trustWhich misses the swap
89 · trustAnd the PKI build does not
90 · trustThe presented id does not match the pin
91 · trustNor what the root signed
92 · trustSo the PKI build refuses
93 · trustAnd so does trust-on-first-use, on a later attach
94 · trustThe id matches the pin
95 · trustBut the root did not verify
96 · trustAnd the PKI build refuses
97 · trustThe root signed the new device too
98 · trustSo both builds trust it
99 · trustSix attaches
100 · trustThe PKI build refused three
101 · trustTrust-on-first-use refused one
102 · trustThe PKI build never misses a swap
103 · trustTrust-on-first-use missed the swap and the unverified root
104 · orderLink up is too early to bind
105 · orderSo is the authenticate phase itself
106 · orderThe bind phase may bind
107 · orderBut may not yet serve
108 · orderAnd in use may do both
109 · orderIncluding serve
110 · orderAn unauthenticated device may not bind
111 · orderThe after-use build binds it
112 · orderWhich is a premature bind
113 · orderAnd the correct build makes none
114 · orderNor may it serve
115 · orderThe after-use build serves it host memory
116 · orderSix ordering steps
117 · orderThe correct build never binds unauthenticated
118 · orderThe after-use build did twice
119 · orderAnd reported no premature bind
120 · orderAgainst the after-use build's two
121 · policyA successful authentication is admitted
122 · policyAnd not refused
123 · policyWith no fail-open
124 · policyIn either build
125 · policyA failed authentication is not admitted at full privilege
126 · policyBut a degraded mode is available
127 · policySo it is not refused outright
128 · policyThe fail-open build admits it fully
129 · policyWhich is a fail-open
130 · policyAnd the correct build makes none
131 · policyStill not admitted
132 · policyWith no degraded mode
133 · policySo it is refused
134 · policyThe fail-open build admits it regardless
135 · policyThree authentication results
136 · policyOne admitted
137 · policyOne refused
138 · policyThe fail-open build admitted all three
139 · policyThe correct policy never fails open
140 · policyThe fail-open build did on both failures
141 · costAn access after attach costs only the access
142 · costThe per-access build charges authentication every time
143 · costWhich is a per-access charge
144 · costAnd the correct build makes none
145 · costOne access amortises to 50300ns
146 · costSo authentication is on the critical path
147 · costA thousand accesses amortise to 350ns
148 · costA 14 percent share
149 · costStill on the critical path
150 · cost1470 accesses amortise to 334ns
151 · costAn exactly ten percent share
152 · costWhich is not on the critical path
153 · cost1400 accesses is still ten percent
154 · costTen thousand accesses amortise to 305ns
155 · costA one percent share
156 · costSo it is off the critical path
157 · costThe correct build totalled 1500ns over five accesses
158 · costThe per-access build totalled 251500ns
159 · costThe correct model never charges per access
160 · costThe per-access build charged on all five
161 · reauthA recent authentication need not be repeated
162 · reauthAnd the trust is not stale
163 · reauthWith nothing reported
164 · reauthIn either build
165 · reauthAt the maximum age it must re-authenticate
166 · reauthThe once-only build never does
167 · reauthSo its trust is stale
168 · reauthWhich is reported
169 · reauthAnd the correct build reports none
170 · reauthOne below the maximum does not
171 · reauthA firmware update forces re-authentication
172 · reauthThe once-only build carries on trusting the old measurement
173 · reauthWhich is stale trust
174 · reauthA link reset forces it too
175 · reauthFive ticks
176 · reauthThree re-authentications required
177 · reauthThe once-only build required none
178 · reauthThe correct build never trusts stale
179 · reauthThe once-only build did on all three
180 · authAll five gates pass
181 · authSo the device is authenticated
182 · authThe measurement gate alone is failing
183 · authSo the correct verifier refuses
184 · authThe signature-only build authenticates it
185 · authWhich is a weak authentication
186 · authAnd the correct build makes none
187 · authThe freshness gate alone, also missed
188 · authThe chain gate alone, also missed
189 · authThe revocation gate alone, also missed
190 · authThe signature gate alone, seen by both
191 · authSix authentication evaluations
192 · authOne device authenticated
193 · authThe signature-only build authenticated five

18. Mutation Testing

74 mutations, one at a time, each required to make the baseline print RESULT: FAIL.

74 of 74 were killed.

The first run killed 69 and left 5 survivors:

ClassCount, and the fix
Stimulus gap3 · an invalid signature over a stale nonce; a non-matching pin; a root that did not verify
Boundary never driven1 · construct the access count giving exactly 10%
Unobserved output1 · assert the running cost total

Three are worth stating.

"Replay reported on an invalid signature" survived because no stimulus combined a bad signature with a stale nonce. The bench had driven each independently. Adding the combination proved the checker distinguishes a replay — a valid response to a repeated challenge — from an ordinary failure that happens to be over a reused nonce.

"Root match ignores whether the root verified" survived because root_ok was never driven low. An identity matching what the root would have signed proves nothing if the root's own signature did not verify, and until that case existed the term was unexercised.

The critical-path boundary at exactly 10% had to be solved for. The share is (amortised − access) × 100 / amortised, and it equals exactly 10 only when the amortised cost is 334 ns — which happens at 1470 accesses and at no round number near it.

A representative sample:

MutationResult
A match without a golden valueKILLED
Any measurement matchesKILLED
The correct verifier accepts everythingKILLED
Blind acceptance without acceptingKILLED
The correct build uses a static nonceKILLED
Every nonce is freshKILLED
Freshness invertedKILLED
Acceptance ignores freshnessKILLED
A replay reported on an invalid signatureKILLED
The intermediate is always validKILLED
The correct build skips the intermediateKILLED
Nothing is ever revokedKILLED
Revocation invertedKILLED
Acceptance ignores list freshnessKILLED
Acceptance ignores the revocation itselfKILLED
Every identity matches the pinKILLED
The root match ignores whether the root verifiedKILLED
The PKI build trusts the pinKILLED
A swap reported without trustingKILLED
The correct build binds unauthenticatedKILLED
Binding allowed at the authenticate phaseKILLED
Serving allowed at the bind phaseKILLED
The correct policy admits everythingKILLED
Degraded admitted with no degraded modeKILLED
Refusal ignores the degraded pathKILLED
The correct build charges per accessKILLED
The critical-path boundary is off by oneKILLED
The age boundary is off by oneKILLED
A firmware update is not an eventKILLED
A link reset is not an eventKILLED
Stale trust without a triggerKILLED
The signature-only build checks everythingKILLED

19. Verification Strategy

Two builds, one stimulus. The parameter is the only difference, and in this chapter the "broken" build is always a verifier that skips a check.

Combine the failures, not just enumerate them. A bad signature and a stale nonce had each been driven; the combination had not, and it was the only stimulus that proved what a replay means.

Drive every term of every conjunction to zero. root_ok low; golden_known low; list_fresh low. Each is a term whose absence changes the answer and each was initially untested.

Construct the boundary. The 10% critical-path share exists at 1470 accesses and nowhere near a round number.

Drive the case where the weaker build is correct. A valid signature with everything else passing; a first attach where trust-on-first-use and a PKI agree; a chain whose leaf is bad, which both builds catch. In each, a checker that fired would fire on a good case.

Assert the running total, not only the per-event value. One frozen-counter survivor here, against four in 18.1 — the habit is transferring.

20. Synthesis and Implementation Reality

No cryptography is modelled and that is deliberate. sig_valid is an input. A real implementation needs a verified signature routine, a hash the device and host agree on, and a way to hold a root of trust — none of which this chapter attempts, and all of which are where the actual security lives.

The trust store is the hard part. Section 5 needs a golden measurement, section 7 needs a trusted root and section 9 needs a current revocation list. All three arrive from outside the link and all three are provisioning problems: a verifier is only as good as the values it was given, and nothing in the protocol provides them.

Section 14's re-authentication competes with section 13's cost. Re-authenticating often is safer and puts a 50 µs operation on the path more frequently. The right interval depends on what the deployment can detect between checks, which is a policy question rather than a protocol one.

Section 11's ordering is the cheapest thing on this list to get right and the easiest to get wrong. It costs nothing to gate the bind on the authentication result; it requires only that the enumeration path and the authentication path be sequenced, which is a state-machine decision made early and hard to change later.

A degraded mode has to exist before it can be used. Section 12's middle outcome is only available if the deployment has somewhere to put a device that failed attestation, and building that is more work than the authentication itself.

21. Silicon Observability

ObservableWhy it matters
Authentication attempts, successes and failures, separatelysection 12 — a fail-open system reports no failures
Which gate failed, per refusalsection 15 — a single "refused" bit sends an engineer to five places
Whether a golden measurement existed for each devicesection 5 — accepting for want of a comparison looks like accepting
Revocation-list age at each checksection 9 — a stale list must be distinguishable from a clean one
Time since last authentication, per devicesection 14 — trust has an expiry only if somebody measures it
Binds performed while unauthenticatedsection 11 — should be zero and is worth counting

The third row is the one that hides. A verifier with no golden value and a verifier whose comparison passed both report "accepted", and only an explicit record of whether a comparison was possible distinguishes them. That is the difference between an attested fleet and a fleet nobody has ever attested.

22. Debug Lab

Symptom: a device that should not have been admitted is serving host memory.

Check whether authentication ran before the bind. Section 11: an after-use ordering binds on the device's own description, and the authentication result arrives afterwards where it changes nothing.

Check what the failure policy does. Section 12: a system with no failure path admits on failure, and the admission looks identical to a success in every log.

Check whether a golden measurement existed. Section 5: with nothing to compare against, "accepted" means "not checked".

Check the nonce. Section 6: a static or predictable nonce means a recorded response authenticates forever, and the device need not be present at all.

Check the whole chain, not the ends. Section 7: the skipping build catches a bad leaf and an untrusted root and misses the intermediate.

Check the revocation list's age. Section 9: a stale list produces acceptances that are indistinguishable from clean ones unless the age is recorded.

Check when the device last authenticated, and whether its firmware changed since. Section 14: an attestation from before an update certifies software that is no longer running.

23. Design Review

Where does the golden measurement come from, and what happens when there is not one?

Is the nonce fresh per challenge, and who generates it?

Is every link in the chain validated, or only the ends?

Is the revocation list consulted, and what does a stale list do?

Does the bind depend on the authentication result? If the two are independent state machines, the answer is no whatever the intent was.

What happens when authentication fails? If nobody can state the policy, it is fail-open.

When is a device re-authenticated? Age, link reset and firmware update are three different triggers and each needs an answer.

24. How This Appears In Real Engineering

Authentication failures do not present as security incidents. They present as systems where authentication was configured, ran, and established nothing.

The characteristic case is a fleet with no golden measurements. CMA is enabled, measurements are retrieved and logged, and nothing compares them against anything — so every device passes and the logs are a record of what firmware was running rather than a check on it.

The second is authentication that runs after enumeration and binding. The exchange completes, the result is recorded, and the device has had host memory since before the challenge was issued.

The third is a fail-open policy nobody chose. Authentication fails, the code path handling that failure does not exist, and the device is admitted — with a log line that reads identically to a success.

The fourth is trust that never expires. A device authenticated at first attach, a firmware update six months later, and an attestation that now certifies software that has been replaced.

25. Common Misconceptions

"The device is authenticated — the signature verified." A valid signature proves the device holds a private key. Which key, whether that key is still trusted, and what the device is running are three further questions.

"We retrieve measurements, so we do attestation." Retrieval is a protocol exchange. Attestation is a comparison, and it needs a value the device did not supply.

"The chain validated." All of it, or the two ends? The intermediate is the link that requires an extra fetch and the one a mis-issued certificate uses.

"The certificate is valid." Validity and revocation are separate questions, and a stale revocation list answers neither.

"We authenticate at attach." Before or after the bind? After it, the device has had host memory for the duration of the exchange.

"Trust on first use is good enough." It misses a device swapped for one presenting the same identity, which is the case it was chosen to be cheap about.

"Authentication is expensive so we do it once." It is cheap because it happens once — 1% of an access across ten thousand. The question is not the cost but what invalidates the result.

"Nothing failed authentication this quarter." In a fail-open system, nothing ever does. That statistic is compatible with authentication having never worked.

26. Interview Reasoning

Q1. A device's signature verifies. What have you established? That it holds a private key. Not which key, not whether that key's certificate is still trusted, and nothing about its firmware.

Q2. You retrieve a measurement over SPDM. Is that attestation? Only if you compare it against a value obtained independently. Retrieval without comparison is a protocol exchange that establishes nothing.

Q3. What does a verifier with no golden measurement do? Refuse. Accepting for want of anything to compare against is indistinguishable, in every log, from accepting because the comparison passed.

Q4. Why must the nonce be fresh? Because a signature over a reused nonce is a recording. It proves the device was there once, not that it is there now — and the device need not be present at all.

Q5. An invalid signature over a stale nonce. Is that a replay? No. A replay is a valid response to a challenge that has been asked before. Reporting one on every failed signature turns the metric into a failure count.

Q6. Which link in a certificate chain is most often skipped? The intermediate. The leaf and the root are the two the verifier naturally has; the middle requires a fetch, and it is the link a mis-issued certificate exploits.

Q7. Your revocation list is a week old. Do you accept? No. You do not know whether the certificate has been withdrawn, and treating "could not check" as "checked out" makes revocation infrastructure pointless.

Q8. Trust on first use against a PKI — which is better? They fail differently. Trust on first use needs no provisioning and misses a swapped device presenting the pinned identity. A PKI catches the swap and trusts everything a compromised root signs.

Q9. When must authentication complete? Before the bind. After it, the device can read and write host memory, and the exchange is establishing something about a device that already has what it wanted.

Q10. What happens when authentication fails? Whatever the policy says. Refuse, admit at reduced privilege, or admit — and if nobody wrote the policy down, the code path does not exist and the device is admitted.

Q11. Is authentication expensive? Not per access — it is 1 percent across ten thousand accesses. It is expensive only if it is on the per-access path, which nobody does deliberately.

Q12. What invalidates an earlier authentication? Age, a link reset and a firmware update. The third is the sharpest: the measurement was of software that is no longer running.

Q13. Your fleet reports zero authentication failures. Is that good? It is compatible with a fail-open system in which authentication never worked, and with a fleet that has no golden measurements. Zero failures is not evidence of success.

Q14. What do you record on a refusal? Which gate failed. A single "refused" bit sends an engineer to five separate subsystems.

Q15. Which of the five gates does a valid signature satisfy? One. Freshness, chain, revocation and measurement are all independent of it, which is why the signature-only build in section 15 authenticates five devices out of six.

Q16. What is the hardest part of implementing this? The trust store. The golden measurements, the root and the revocation list all arrive from outside the link, and a verifier is only as good as the values it was provisioned with.

27. Exercises

1. Extend RTL 1 to hold several golden measurements, one per approved firmware version. What does measurement_ok become, and what does a version nobody approved report?

2. In RTL 2, model a nonce generated from a counter rather than randomly. Which of the freshness assertions still hold, and what does an attacker who can observe the counter gain?

3. RTL 3 has three links. Generalise to a chain of depth n and determine whether the failure mask still fits in a fixed width.

4. Add a grace period to RTL 4 during which a stale list is accepted. Using 18.5 section 10's reasoning, what should bound it?

5. In RTL 5, model a PKI whose root is itself revoked. What does root_match mean then, and which model detects it?

6. RTL 6 gates the bind. Add a re-bind after a link reset and determine which of section 14's triggers must force a full re-authentication rather than a cached result.

7. Using RTL 8 and RTL 9 together, find the re-authentication interval at which authentication returns to the critical path for a workload with 1000 accesses between checks.

8. Add a sixth gate to RTL 10 for the link security of 19.2. Is it independent of the other five, and does authentication have to complete before it can be established?

28. Summary

Every earlier chapter assumed the device was what it claimed. This one checks.

A measurement needs something to compare against. Two of three verifications rejected — one for a mismatch and one for having no golden value at all.

A challenge must be fresh. A static nonce let one recorded response answer three challenges, and the device need not have been present.

Every link in the chain. The skipping build caught both ends and missed the intermediate, which is the link an extra fetch would have covered.

Revocation is a separate question, and a stale list is a refusal — "could not check" is not "checked out".

Trust on first use missed two swaps the PKI build caught, and needed no provisioning to do it. Different failure modes, not a better and a worse.

Authentication must complete before the bind. Two devices given host memory on their own description, by an ordering that authenticated afterwards.

A failure needs a policy — refuse, degrade, or admit. The build without one admitted all three results at full privilege.

And trust expires. Age, link reset, firmware update — three triggers, and the once-only build honoured none of them while continuing to certify firmware that had been replaced.

A valid signature passes one gate of five. It answers "does this device hold a key" and leaves which key, is it still trusted, and what is it running entirely open.

19.2 — Secure Communication takes a device whose identity is established and asks the next question: what protects the traffic that follows.

Continue learning

Standards & specifications

Governing standard
CXL Specification (CXL Consortium)(opens CXL Consortium in a new tab)

Defines CXL.io, CXL.cache and CXL.mem, and the coherence and memory-pooling behaviour built on them. System design and deployment topology are not mandated.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the CXL curriculum.