Skip to content
VLSI Mentor

CXL · Module 19

Secure Communication

Authentication established who is on the link. This chapter protects what crosses it: integrity against confidentiality, MAC strength, replay counters, key lifetime, IV uniqueness, the bandwidth overhead, selective protection, downgrade negotiation and verification failure.

19.1 established who is on the other end of the link. It said nothing about what happens to the traffic afterwards.

An authenticated device on an unprotected link is a device whose identity is known and whose flits anybody on the path can read, modify or replay. This chapter is the other half.

1. The Engineering Problem — Encryption Is Not Protection

Six things separate a protected link from an encrypted one.

Integrity and confidentiality are separate properties, and only one of them stops an attacker changing what you receive. A link with encryption and no MAC accepts modified ciphertext without noticing. Section 5.

A MAC is a probability. Its length decides how many forgeries an attacker expects to try, and a truncated MAC is a work factor somebody can reach. Section 6.

Replay needs a counter. A flit that verifies perfectly and has been seen before is a recording, and a receiver with no sequence check cannot distinguish it from a new one. Section 7.

A key has a lifetime measured in data and in sequence numbers, and rekeying must happen before either runs out — because a wrapped counter makes an old flit look new. Section 9.

An initialisation vector must never repeat under one key. Reuse is not a weakness of the cipher; it is a failure of the counter that feeds it. Section 10.

And negotiation must not be able to select nothing. A downgrade an attacker can force is a downgrade an attacker will force. Section 13.

This chapter against 19.1, stated precisely. That one owns establishing identity, once, at attach. This one owns protecting every flit afterwards — and section 15 shows that the first is a property of the second rather than an alternative to it.

2. The One-Sentence Model

A secure link knows who is at the other end, detects modification, rejects repetition, and uses keys that have not run out — and every defect below is a link with encryption and one of those four missing.

3. What This Chapter Owns

GroundOwner
Establishing which device this is19.1
Isolating hosts and tenants that share a pool19.3
Policy enforcement across tenants19.4
The bandwidth ceiling the overhead eats into18.2
Protecting the traffic on an established linkthis chapter

Deferred:

Deferred groundOwner
Cryptographic primitives themselvesout of scope — see §4
Isolation between tenants on one device19.3
Key provisioning and distributionout of scope — see §20
Side channels and traffic analysis beyond §12out of scope

4. Teaching-Model Boundary

Sixteen-bit sequence numbers, a four-way traffic classification and a three-level negotiation 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: integrity and confidentiality as independent properties, a work factor derived from MAC length, a monotonic counter with an explicit wrap condition, a key lifetime bounded by two separate limits, an IV compared within a key epoch, and a negotiated level compared against a policy floor.

Three things are absent by design. Cryptography is out of scope — a chapter that modelled AES badly would be worse than one that treats it as an input. Key provisioning is out of scope: section 9 says when to rekey and nothing about how the new key is established. And traffic analysis beyond section 12 is out of scope — the model shows that unprotected addresses leak the access pattern and does not attempt to quantify what an observer learns.

5. RTL 1 — Integrity And Confidentiality Are Different

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Integrity and confidentiality are separate properties. Protecting one says
// nothing about the other.
module protection_class #(parameter int ENCRYPT_ONLY = 0) (
  input  logic clk, rst_n,
  input  logic       send,
  input  logic       mac_present, cipher_on,
  output logic       integrity_ok, confidential, both,
  output logic [7:0] n_sent, n_unprotected,
  output logic       tamper_blind_err
);
  // A MAC detects modification. Encryption hides content. Neither implies the
  // other, and a link with only encryption accepts modified ciphertext.
  assign integrity_ok = (ENCRYPT_ONLY != 0) ? 1'b0 : mac_present;
  assign confidential = cipher_on;
  assign both         = integrity_ok && confidential;
  // Sending on a link that cannot detect modification.
  assign tamper_blind_err = send && !integrity_ok;
  // ... send counters omitted for length
endmodule

Three configurations:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  protect: sends=3 unprotected=2 | encrypt-only tamper-blind=3
ConfigurationWhat it gives, and what it misses
MAC and cipherintegrity and confidentiality — not tamper-blind
MAC, no cipherintegrity, no confidentiality — not tamper-blind
Cipher, no MACconfidentiality, no integritytamper-blind

The second and third rows are the whole argument. A MAC without a cipher is a real and useful configuration — the traffic is readable and cannot be modified undetected. A cipher without a MAC is a link where an attacker cannot read the traffic and can still change it, and the receiver will decrypt whatever arrives and act on the result.

6. RTL 2 — A MAC Is A Probability

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// A MAC is a probability, not a guarantee. Its length decides how many forgeries
// an attacker expects to try.
module mac_strength (
  input  logic clk, rst_n,
  input  logic        evaluate,
  input  logic [7:0]  mac_bits,
  input  logic [15:0] attempts_k,
  output logic [31:0] work_log2, expected_k,
  output logic        adequate, truncation_err
);
  // Forging a MAC of n bits takes 2^(n-1) expected attempts. Carrying the
  // exponent rather than the value keeps the arithmetic in range.
  assign work_log2 = (mac_bits == 8'd0) ? 32'd0 : ({24'd0, mac_bits} - 32'd1);
  assign expected_k = {16'd0, attempts_k};
  assign adequate   = (work_log2 >= 32'd63);
  // A MAC short enough that the stated attempt budget can forge one.
  assign truncation_err = evaluate && (work_log2 < 32'd32);
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  mac: bits=64 work=2^63 adequate=1 truncated=0
MAC lengthExpected forgery work and Verdict
64 bits2^63 · adequate
63 bits2^62 · just short
33 bits2^32 · at the truncation boundary, inside it
32 bits2^31 · truncated — reachable
0 bits2^0 · no MAC at all

The work factor is carried as an exponent rather than a value, because 2^63 does not fit anywhere sensible and the comparison only ever needs the exponent. That is a modelling choice worth naming: a quantity that only appears inside comparisons does not need to be materialised.

The truncation threshold at 2^32 is not arbitrary — it is roughly the point at which a determined attacker's forgery budget becomes a number rather than a fantasy. A truncated MAC does not fail; it becomes a thing somebody can afford to attack, and the difference between 32 bits and 64 is the difference between a budget and an impossibility.

7. RTL 3 — Replay Needs A Counter

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// A replay counter must be monotonic, and a receiver must reject anything it has
// already seen.
module replay_counter #(parameter int ACCEPT_ANY = 0) (
  input  logic clk, rst_n,
  input  logic        rx,
  input  logic [15:0] seq_in,
  output logic [15:0] highest_seen,
  output logic        accepted, is_replay, wrapped,
  output logic [7:0]  n_rx, n_dropped,
  output logic        replay_accept_err
);
  assign is_replay = (seq_in <= highest_seen);
  // Wrapping the counter makes an old sequence number look new, which is why a
  // rekey has to happen before the counter can wrap.
  assign wrapped   = (highest_seen == 16'hFFFF);
  // The accepting build takes anything, which is a link with no replay
  // protection at all however good its MAC is.
  assign accepted = (ACCEPT_ANY != 0) ? 1'b1 : !is_replay;
  // Accepting a sequence number that has already been used.
  assign replay_accept_err = rx && accepted && is_replay;
  // ... receive counters omitted for length
endmodule

Five flits:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  replay: rx=5 dropped=2 highest=50 | accepting build accepted=2
SequenceHighest seen and Verdict
10 · accept
21 · accept
2 again2 · replay — drop
12 · replay — drop
50 — a jump forward2 · accept

A gap is not a replay. Sequence 50 after sequence 2 means 47 flits were lost, which is a reliability question rather than a security one — and a receiver that rejected gaps would reject every lossy link. The comparison is <= against the highest seen, not != highest + 1.

wrapped exists to connect this model to section 9. A sixteen-bit counter at FFFF has nowhere to go: the next flit either stalls the link or wraps to zero, and a wrapped counter makes every old flit look new again. That is why the rekey in section 9 is bounded by sequence space as well as by bytes.

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

An eight-cycle waveform showing flits arriving on a protected link. Each flit carries a sequence number and a MAC that verifies. Two of the flits repeat a sequence number already seen; the correct receiver drops them while the accepting build delivers them. A jump forward in sequence is accepted by both as a gap rather than a replay.sequence 2 repeatssequence 2 repeatsan older onean older onea gap, not a replaya gap, not a replaytwo delivered twicetwo delivered twiceclkseq_in122150515253mac_okhighest01222505152replayacceptany_accdelivered12223456t0t1t2t3t4t5t6t7
Figure 1 — The mac_ok row is high on every cycle: all eight flits verify, including the two replays. Integrity and replay protection are independent, and a receiver with a perfect MAC and no counter is the any_acc row, which never drops anything.

The mac_ok row being flat at 1 is the point. A replayed flit is a genuine flit that was genuinely sent by the genuine device — its MAC verifies because it is a real MAC over real data. Integrity checking cannot detect a replay, and that is why the counter is a separate mechanism rather than a property of the MAC.

9. RTL 4 — A Key Has A Lifetime

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// A key has a lifetime measured in the data it protects, and rekeying must
// happen before the counter that guarantees uniqueness runs out.
module key_lifetime #(parameter int NEVER_REKEY = 0) (
  input  logic clk, rst_n,
  input  logic        transmit,
  input  logic [31:0] bytes_sent, byte_budget,
  input  logic [15:0] seq_now, seq_max,
  output logic        budget_spent, seq_exhausted, must_rekey,
  output logic [7:0]  n_tx, n_rekeys,
  output logic        overrun_err
);
  assign budget_spent  = (bytes_sent >= byte_budget);
  assign seq_exhausted = (seq_now >= seq_max);
  // Either limit forces a rekey. The never-rekey build keeps going, which
  // eventually reuses a sequence number under the same key.
  assign must_rekey = (NEVER_REKEY != 0) ? 1'b0 : (budget_spent || seq_exhausted);
  // Transmitting past a limit that should have forced a rekey.
  assign overrun_err = transmit && (budget_spent || seq_exhausted) && !must_rekey;
  // ... transmit counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  key: tx=5 rekeys=2 | never-rekey overruns=2

Two independent limits, and either one alone forces a rekey:

Bytes sentSequence and Rekey required
1,000 of 100,00010 of 1000 · no
exactly 100,00010 · yes — the byte budget
99,99910 · no — one byte short
1,000exactly 1000 · yes — the sequence space
1,000999 · no — one short

The bench drives each limit alone and each boundary exactly, because the two mutations that reduce must_rekey to one term or the other are killed by different rows.

The sequence limit is the one that surprises people. A link nowhere near its data budget can still exhaust a sixteen-bit sequence counter, and section 7's wrapped output is what happens next: the counter returns to zero, every old flit becomes acceptable again, and the replay protection built so carefully in section 7 evaporates.

A state machine showing the lifecycle of a link key. From fresh, ordinary transmission returns to fresh while both budgets hold. Spending the byte budget or exhausting the sequence space moves the key to spent, from which a rekey returns it to fresh. A build that never rekeys instead moves from spent to wrapped, where old sequence numbers become acceptable again.FRESHSPENTREKEYWRAPPEDtransmittingtransmittingbytes or sequencebytes or sequencerekey issuedrekey issuednew epochnew epochno rekeyno rekey
Figure 2 — WRAPPED has no exit. A key that reaches it has a sequence counter back at zero and an IV space already used, so every old flit is acceptable again and section 10's uniqueness no longer holds. The only edge out of SPENT that avoids it is the rekey.

The absence of an edge out of WRAPPED is the point. There is no recovery: the sequence space has already been reused under the key, the IVs have already repeated, and no amount of later care undoes flits that were accepted in the meantime. The rekey is not a maintenance operation — it is the only transition that keeps the state machine out of a terminal state, and section 9's two limits exist to force it before the edge to WRAPPED is taken.

10. RTL 5 — An IV Must Never Repeat Under One Key

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// An initialisation vector must never repeat under one key. Reuse is not a
// weakness of the cipher; it is a failure of the counter that feeds it.
module iv_uniqueness #(parameter int REUSE_IV = 0) (
  input  logic clk, rst_n,
  input  logic        encrypt,
  input  logic [15:0] iv_in, key_epoch, last_iv, last_epoch,
  output logic [15:0] iv_used,
  output logic        unique_iv, same_key,
  output logic [7:0]  n_encrypt, n_reused,
  output logic        iv_reuse_err
);
  assign same_key  = (key_epoch == last_epoch);
  // A repeated IV is only a problem under the same key: a rekey resets the space.
  assign iv_used   = (REUSE_IV != 0) ? 16'h00FF : iv_in;
  assign unique_iv = !same_key || (iv_used != last_iv);
  // Encrypting with an initialisation vector already used under this key.
  assign iv_reuse_err = encrypt && !unique_iv;
  // ... encryption counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  iv: encryptions=5 reused=1 | reusing build reused=2

The !same_key term is what makes this model correct rather than merely strict. An IV repeated under a different key is not a reuse — a rekey resets the IV space entirely, and a model that forbade repetition across epochs would forbid the only mechanism that makes a finite IV space workable:

This encryptionAgainst the last one, and the verdict
IV 1, epoch 1last IV 0, same epoch — unique
IV 1, epoch 1last IV 1, same epoch — a reuse
IV 1, epoch 2last IV 1, different epoch — unique again
12 · 1 · 1 · yes — different key

This is the same structure as section 9's sequence limit seen from the other side: the rekey is what makes both counters finite and safe. Without it, the IV space and the sequence space are both finite and both eventually repeat.

11. RTL 6 — Security Costs Bandwidth

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Security costs bandwidth. The MAC is bytes on the wire that carry no payload,
// and 18.2's ceiling applies to the total.
module security_overhead #(parameter int IGNORE_OVERHEAD = 0) (
  input  logic clk, rst_n,
  input  logic        send,
  input  logic [15:0] payload_b, mac_b, iv_b, flit_b,
  output logic [31:0] on_wire_b,
  output logic [7:0]  overhead_pct, efficiency_pct,
  output logic [15:0] effective_gbps,
  input  logic [15:0] raw_gbps,
  output logic        overhead_blind_err
);
  logic [31:0] ov_q, ef_q, eg_q;
  // Every protected flit carries a MAC and an IV alongside its payload.
  assign on_wire_b = (IGNORE_OVERHEAD != 0) ? {16'd0, payload_b}
                   : ({16'd0, payload_b} + {16'd0, mac_b} + {16'd0, iv_b});
  // A build that does not count the MAC and IV on the wire cannot report their
  // share either: it has no way to know they are there.
  assign ov_q = (IGNORE_OVERHEAD != 0) ? 32'd0
              : ((on_wire_b == 32'd0) ? 32'd0
                 : ((({16'd0, mac_b} + {16'd0, iv_b}) * 32'd100) / on_wire_b));
  // ... efficiency and effective rate omitted for length
  // Reporting no overhead on a link that is carrying a MAC.
  assign overhead_blind_err = send && (mac_b != 16'd0) && (overhead_pct == 8'd0);
endmodule

A 16-byte MAC and an 8-byte IV on a 400 Gbps link:

PayloadOn the wire, overhead, and payload delivered
8 bytes32 on the wire · 75% overhead · 100 Gbps delivered
64 bytes88 on the wire · 27% overhead · 288 Gbps delivered
256 bytes280 on the wire · 8% overhead · 364 Gbps delivered
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  overhead: on_wire=88B overhead=27% effective=288Gbps | ignoring blind=3

A 400 Gbps link protecting 64-byte payloads delivers 288 Gbps of payload. The other 112 is MAC and IV, and 18.2's entire ceiling analysis applies to the 400, not the 288 — which means security overhead sits alongside flit efficiency as a second multiplier on the same raw rate.

This is 18.3 section 13's small-access argument in a third setting. At an 8-byte payload the security overhead is 75% — three bytes of protection for every byte protected — which is a strong argument for batching that has nothing to do with the API cost that chapter modelled.

The no-MAC case is driven and is not blindness: a link genuinely carrying no MAC has genuinely no overhead, and a checker that fired there would fire on every unprotected link.

12. RTL 7 — What Is Left In The Clear

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Protecting some traffic and not the rest. What is left in the clear is a
// policy decision, and the metadata usually is.
module selective_protection #(parameter int PROTECT_DATA_ONLY = 0) (
  input  logic clk, rst_n,
  input  logic       send,
  input  logic [1:0] traffic,      // 0 data, 1 address, 2 control, 3 management
  output logic       protected_now,
  output logic [3:0] exposed_mask,
  output logic [7:0] n_sent, n_clear,
  output logic       metadata_leak_err
);
  // Protecting payloads and leaving addresses in the clear leaks the access
  // pattern, which for a memory device is most of what an observer wants.
  assign protected_now = (PROTECT_DATA_ONLY != 0) ? (traffic == 2'd0) : 1'b1;
  assign exposed_mask[0] = (PROTECT_DATA_ONLY != 0) ? 1'b0 : 1'b0;
  assign exposed_mask[1] = (PROTECT_DATA_ONLY != 0) ? 1'b1 : 1'b0;  // addresses
  assign exposed_mask[2] = (PROTECT_DATA_ONLY != 0) ? 1'b1 : 1'b0;  // control
  assign exposed_mask[3] = (PROTECT_DATA_ONLY != 0) ? 1'b1 : 1'b0;  // management
  // Sending address or control traffic in the clear.
  assign metadata_leak_err = send && (traffic != 2'd0) && !protected_now;
  // ... send counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  selective: sends=4 clear=0 | data-only clear=3 leaks=3

The data-only build sends three of four traffic classes in the clear, and for a memory device those three are most of what an observer wants:

Traffic classWhat it reveals if unprotected
Datathe contents — which is what everybody protects
Addressesthe access pattern — which pages, in what order, how often
Controlthe transaction mix and the protocol in use
Managementthe fabric's own configuration traffic

The address stream is the sharpest of the three. For a CXL memory device, the sequence of addresses is a very good description of what the workload is doing18.3 built four chapters' worth of inference from exactly that signal, and an observer with the address stream has the same material.

exposed_mask names which classes are in the clear rather than reporting a single "partially protected" bit, for the reason every failure mask in this track exists: a policy decision needs to be visible at the granularity it was made.

13. RTL 8 — Negotiation Must Have A Floor

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Negotiation must not be able to select nothing. A downgrade an attacker can
// force is a downgrade an attacker will force.
module security_negotiate #(parameter int ALLOW_NONE = 0) (
  input  logic clk, rst_n,
  input  logic       negotiate,
  input  logic [1:0] host_level, dev_level,   // 0 none, 1 integrity, 2 integrity+confidentiality
  input  logic [1:0] policy_floor,
  output logic [1:0] agreed_level,
  output logic       meets_floor, downgraded,
  output logic [7:0] n_negotiations, n_refused,
  output logic       downgrade_err
);
  logic [1:0] lower;
  assign lower = (host_level < dev_level) ? host_level : dev_level;
  // The permissive build accepts whatever the pair can agree on, including
  // nothing. The correct build refuses below a configured floor.
  assign agreed_level = (ALLOW_NONE != 0) ? lower
                                          : ((lower >= policy_floor) ? lower : 2'd3);
  assign meets_floor = (lower >= policy_floor);
  assign downgraded  = (lower < host_level);
  // Agreeing a level below the configured floor.
  assign downgrade_err = negotiate && (ALLOW_NONE != 0) && !meets_floor;
  // ... negotiation counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  negotiate: negotiations=5 below_floor=2 | permissive downgrades=2
Host and deviceWhat is agreed, against an integrity floor
both / bothagrees on both — meets the floor
both / integrity onlyagrees on integrity — a downgrade, and permitted
both / nonerefused — below the floor

A downgrade is not automatically a failure. The second row is a legitimate outcome: the device cannot do confidentiality, the pair agree on integrity, and integrity is above the floor. The distinction the model draws is between a downgrade and a downgrade below what policy allows, and only the second is an error.

The floor is compared inclusively and driven exactly: a level exactly at the floor meets it, and a floor one above the agreed level does not.

The permissive build's failure is that it has no floor at all. It agrees on whatever the two ends can both do, which means a device claiming to support nothing gets a link with nothing — and an attacker who can influence what the device claims gets to choose.

A block diagram of a protected CXL link. A payload enters an encryption stage and then a MAC stage, which adds an authentication tag, and a sequence number is attached before transmission. At the receiver the MAC is verified, the sequence is checked against the highest seen, and only then is the payload decrypted and delivered. A dashed path bypasses both the MAC check and the sequence check, going straight from receive to deliver.payload64 bytesencryptunique IVadd MAC16 bytesadd sequencemonotonicverify + checkMAC then sequencedeliver88 on the wire, 64usefulno checksencryption aloneplaintextciphertexttaggedtransmittedboth passskips both12
Figure 3 — Three stages are added on transmit and two checks are performed on receive. The dashed path is the encryption-only link: the payload is unreadable in transit and arrives having been neither verified nor sequence-checked.

14. RTL 9 — What A Failed Verification Means

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// What a receiver does with a flit whose MAC does not verify. Dropping silently
// and reporting are different, and only one of them is detectable.
module verify_failure #(parameter int SILENT_DROP = 0) (
  input  logic clk, rst_n,
  input  logic        rx,
  input  logic        mac_ok,
  input  logic [15:0] fails_seen, alarm_threshold,
  output logic        deliver, dropped, alarm,
  output logic [7:0]  n_rx, n_dropped,
  output logic        silent_err
);
  assign deliver = mac_ok;
  assign dropped = !mac_ok;
  // A run of verification failures is an attack signature. Dropping without
  // counting makes it indistinguishable from a noisy link.
  assign alarm = (SILENT_DROP != 0) ? 1'b0 : (fails_seen >= alarm_threshold);
  // Dropping a flit that failed verification without raising anything.
  assign silent_err = rx && dropped && (fails_seen >= alarm_threshold) && !alarm;
  // ... receive counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  verify: rx=5 dropped=3 | silent build silent drops=1

One verification failure is a bit error. A hundred is an attack. The individual response is the same either way — drop the flit — and the difference is entirely in whether anybody counts:

Failures seenAlarm
1no — indistinguishable from line noise
7no — one below the threshold
8yes — a signature

The threshold is inclusive and driven exactly. silent_err requires the flit to have been dropped — a verifying flit arriving during a run of failures is delivered normally and is not a silent drop, and the bench drives that case to prove the term earns its place.

A link that drops silently reports perfect health. Every flit that fails verification disappears, the counters that would show it do not exist, and an attacker probing the MAC gets unlimited attempts against section 6's work factor with nobody watching.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Link security assembled: every property a protected link needs before the
// traffic on it can be relied on.
module secure_link #(parameter int ENCRYPTION_ONLY = 0) (
  input  logic clk, rst_n,
  input  logic       evaluate,
  input  logic       peer_authenticated, // 19.1 completed
  input  logic       integrity_present,  // a MAC over every flit
  input  logic       replay_protected,   // a monotonic counter
  input  logic       key_fresh,          // within its byte and sequence budget
  input  logic       floor_met,          // negotiation did not go below policy
  output logic       link_secure,
  output logic [4:0] fail_mask,
  output logic [7:0] n_eval, n_secure,
  output logic       false_security_err
);
  assign fail_mask[0] = ~peer_authenticated;
  assign fail_mask[1] = ~integrity_present;
  assign fail_mask[2] = ~replay_protected;
  assign fail_mask[3] = ~key_fresh;
  assign fail_mask[4] = ~floor_met;
  // The encryption-only build calls a link secure because the traffic is
  // unreadable, which says nothing about who is at the other end or whether the
  // ciphertext has been modified or replayed.
  assign link_secure = (ENCRYPTION_ONLY != 0) ? 1'b1 : (fail_mask == 5'd0);
  assign false_security_err = evaluate && link_secure && (fail_mask != 5'd0);
  // ... evaluation counters omitted for length
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  link: evaluated=6 secure=1 | encryption-only secure=6

One secure link out of six, and the encryption-only build called all six secure. It is the widest gap of any assembled model in this batch, and the reason is that its criterion is not one of the five properties at all — it is "the traffic is unreadable", which none of the five gates measures:

PropertyThe question it answers and Encryption-only
Peer authenticatedwho is at the other end?19.1 · missed
Integrity presenthas this been modified? · missed
Replay protectedhave I seen this before? · missed
Key freshis the key still safe to use? · missed
Floor metdid negotiation give away too much? · missed

The first row is where this chapter and 19.1 join. A perfectly protected link to an unauthenticated peer is a channel whose confidentiality and integrity are established with somebody — and the whole of 19.1 is establishing which somebody. Neither chapter is useful alone.

A flowchart of whether a link may be relied on. A link is established, then checked in turn for whether the peer was authenticated, whether a MAC is present over every flit, whether a monotonic replay counter is enforced, whether the key is within its byte and sequence budgets, and whether negotiation met the policy floor. Passing all five makes the link secure. Failing any one rejects it, and the failure mask names which property is missing.yesyesyesyesyesnoa link is establishedpeerauthenticated?MAC on everyflit?replay counterenforced?key withinbudget?floor met?securenot secure — the masksays why
Figure 4 — Five properties, five rejection paths, and confidentiality is not among them. Encryption is what a link does with the payload once all five hold; it is not one of the conditions and cannot substitute for any of them.

16. Quantitative Reasoning

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

Protection classes. Three configurations, two lacking both properties — and the encrypt-only build was tamper-blind on all three.

MAC strength. 64 bits is 2^63 expected forgeries; 32 bits is 2^31 and reported as a truncation.

Replay. Five flits, two dropped as replays — both with valid MACs. A jump from 2 to 50 is a gap and is accepted.

Key lifetime. Five transmissions, two rekeys — one forced by the byte budget and one by the sequence space alone.

IV uniqueness. Five encryptions, one reuse; the reusing build repeated its single IV twice while being handed fresh ones.

Overhead. 64 + 16 + 8 = 88 bytes on the wire for 64 useful — 27% overhead, and a 400 Gbps link delivering 288 Gbps of payload. At an 8-byte payload the overhead is 75%.

Selective protection. Four traffic classes; the data-only build sent three in the clear.

Negotiation. Five negotiations, two below the floor — refused by the correct build and agreed by the permissive one.

Verification failure. Five flits, three dropped; the alarm threshold is reached at eight failures and the silent build raises nothing.

Assembled. Six evaluations, one secure link against the encryption-only build's six.

17. Assertions

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

# · modelProperty
1 · protectA MAC gives integrity
2 · protectA cipher gives confidentiality
3 · protectSo the link has both
4 · protectAnd is not tamper-blind
5 · protectThe encrypt-only build has no integrity
6 · protectSo it is tamper-blind
7 · protectA MAC without a cipher still gives integrity
8 · protectWith no confidentiality
9 · protectSo not both
10 · protectBut it is not tamper-blind
11 · protectNo MAC is no integrity
12 · protectConfidentiality without it
13 · protectWhich is tamper-blind
14 · protectThree sends
15 · protectTwo of them without both properties
16 · protectThe correct build was tamper-blind once, with no MAC
17 · protectThe encrypt-only build was tamper-blind on all three
18 · macA 64-bit MAC is 2^63 expected attempts
19 · macWhich is adequate
20 · macAnd not a truncation
21 · macA 32-bit MAC is 2^31
22 · macWhich is not adequate
23 · macAnd is reported as a truncation
24 · macA 63-bit MAC is 2^62
25 · macWhich is just short
26 · macA 33-bit MAC is 2^32
27 · macWhich is exactly at the truncation boundary and inside it
28 · macA zero-bit MAC is no work at all
29 · macAnd is a truncation
30 · replaySequence 1 against a highest of 0 is not a replay
31 · replaySo it is accepted
32 · replaySequence 2 is still ahead
33 · replayAnd accepted
34 · replaySequence 2 again is a replay
35 · replaySo the correct receiver drops it
36 · replayThe accepting build takes it
37 · replayWhich is accepting a replay
38 · replayAnd the correct receiver does not
39 · replayAn older sequence is a replay too
40 · replayAnd is dropped
41 · replayA jump forward is not a replay
42 · replayAnd is accepted
43 · replayThe highest seen is 50
44 · replayFive received
45 · replayTwo dropped as replays
46 · replayThe accepting build counted the same two
47 · replayThe correct receiver never accepts a replay
48 · replayThe accepting build accepted both
49 · key1000 bytes of a 100000 budget is not spent
50 · keyAnd sequence 10 of 1000 is not exhausted
51 · keySo no rekey is needed
52 · keyAnd nothing has overrun
53 · keyExactly the budget is spent
54 · keySo a rekey is required
55 · keyThe never-rekey build carries on
56 · keyWhich is an overrun
57 · keyAnd the correct build reports none
58 · keyOne byte short is not spent
59 · keyAnd no rekey is needed
60 · keyThe byte budget is fine
61 · keyBut the sequence space is exhausted
62 · keyWhich forces a rekey on its own
63 · keyAnd the never-rekey build overruns again
64 · keyOne short of the maximum is not exhausted
65 · keyFive transmissions
66 · keyTwo rekeys required
67 · keyThe never-rekey build required none
68 · keyThe correct build never overruns
69 · keyThe never-rekey build overran twice
70 · ivThe same key epoch
71 · ivAnd a new IV is unique
72 · ivWith no reuse
73 · ivThe same IV under the same key is not unique
74 · ivWhich is a reuse
75 · ivA different key epoch
76 · ivSo the same IV is unique again
77 · ivWith no reuse
78 · ivThe correct build's IV is fresh
79 · ivThe reusing build repeats its own
80 · ivWhich is a reuse
81 · ivAnd the correct build reports none
82 · ivA second fresh IV is still unique
83 · ivAnd the reusing build repeats itself again
84 · ivA second reuse
85 · ivFive encryptions
86 · ivOne reuse in the correct build
87 · ivWhich it reported
88 · ivAgainst the reusing build's two
89 · overhead64 plus 16 plus 8 is 88 bytes on the wire
90 · overheadA 27 percent security overhead
91 · overheadLeaving 72 percent efficiency
92 · overheadSo a 400Gbps link delivers 288 of payload
93 · overheadThe ignoring build reports 64 bytes
94 · overheadWith zero overhead
95 · overheadWhich is overhead-blind
96 · overheadAnd the correct build is not
97 · overhead256 plus 24 is 280 bytes
98 · overheadAn 8 percent overhead
99 · overheadDelivering 364 of payload
100 · overhead8 plus 24 is 32 bytes
101 · overheadA 75 percent overhead
102 · overheadDelivering 100 of payload on a 400Gbps link
103 · overheadNo MAC and no IV is no overhead
104 · overheadWhich is not blindness
105 · overheadIn either build
106 · overheadThe correct build is never overhead-blind
107 · overheadThe ignoring build was blind on all three protected sends
108 · selectiveData is protected
109 · selectiveIn both builds
110 · selectiveWith no leak
111 · selectiveThe correct build exposes nothing
112 · selectiveThe data-only build exposes all three metadata classes
113 · selectiveAddresses are protected by the correct build
114 · selectiveAnd left in the clear by the data-only build
115 · selectiveWhich leaks metadata
116 · selectiveAnd the correct build does not
117 · selectiveControl traffic is also in the clear
118 · selectiveAnother leak
119 · selectiveAnd management traffic too
120 · selectiveA third
121 · selectiveFour sends
122 · selectiveThe correct build sent nothing in the clear
123 · selectiveThe data-only build sent three
124 · selectiveAnd the correct build leaked no metadata
125 · selectiveAgainst the data-only build's three
126 · negotiateBoth at the highest level agree on it
127 · negotiateWhich meets the floor
128 · negotiateWith no downgrade
129 · negotiateAnd nothing reported
130 · negotiateA device at integrity only agrees there
131 · negotiateWhich still meets the floor
132 · negotiateThough it is a downgrade from the host's level
133 · negotiateAnd is permitted
134 · negotiateA device at none does not meet the floor
135 · negotiateSo the correct build refuses
136 · negotiateThe permissive build agrees on nothing
137 · negotiateWhich is a downgrade past the floor
138 · negotiateAnd the correct build reports none
139 · negotiateExactly at the floor meets it
140 · negotiateAnd one above it does not
141 · negotiateFive negotiations
142 · negotiateTwo below the floor
143 · negotiateThe correct build never agrees below the floor
144 · negotiateThe permissive build did twice
145 · verifyA verifying flit is delivered
146 · verifyAnd not dropped
147 · verifyWith no alarm
148 · verifyAnd nothing silent
149 · verifyA failing flit is not delivered
150 · verifyIt is dropped
151 · verifyOne failure is below the alarm threshold
152 · verifySo dropping it silently is correct
153 · verifyEight failures reaches the threshold
154 · verifyThe silent build raises nothing
155 · verifyWhich is a silent drop
156 · verifyAnd the correct build is not silent
157 · verifySeven is one short
158 · verifyAnd neither build is silent there
159 · verifyA verifying flit is delivered whatever the history
160 · verifyThough the alarm stands
161 · verifyAnd it is not a silent drop, because it was not dropped
162 · verifyFive flits received
163 · verifyThree dropped
164 · verifyThe correct build never drops silently
165 · verifyThe silent build did once
166 · linkAll five properties present
167 · linkSo the link is secure
168 · linkThe peer-authentication property alone is missing
169 · linkSo the correct build calls the link insecure
170 · linkThe encryption-only build calls it secure
171 · linkWhich is false security
172 · linkAnd the correct build claims none
173 · linkThe integrity property alone, also missed
174 · linkThe replay property alone, also missed
175 · linkThe key-freshness property alone, missed
176 · linkThe floor property alone, also missed
177 · linkSix link evaluations
178 · linkOne secure link
179 · linkThe encryption-only build called all six secure

18. Mutation Testing

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

70 of 70 were killed.

The first run killed 67 and left 3 survivors, of which two were provably equivalent:

ClassCount, and the fix
Unobserved output1 · assert exposed_mask
Provably equivalent2 · replaced

"Leak reported on unprotected data" could not be killed by any stimulus. protected_now is false only when traffic != 0, so the guard (traffic != 2'd0) in the checker can never change the result — the two expressions are identical for every input. The term is defensive and documents intent, and the mutation was replaced.

"Downgrade reported on an upgrade" was the same shape. lower is the minimum of the host and device levels, so lower <= host_level always holds and lower != host_level and lower < host_level coincide. Replaced with one that measures the downgrade against the device instead.

A representative sample:

MutationResult
Integrity without a MACKILLED
The encrypt-only build gains integrityKILLED
Confidentiality from the MACKILLED
Either property counts as bothKILLED
Tamper blindness judged on the cipherKILLED
The work factor is the MAC lengthKILLED
The work factor is unguarded at zeroKILLED
The adequacy boundary is off by oneKILLED
The truncation boundary is off by oneKILLED
The replay boundary is off by oneKILLED
Nothing is ever a replayKILLED
The highest seen is frozenKILLED
The byte-budget boundary is off by oneKILLED
The sequence boundary is off by oneKILLED
A rekey only on the byte budgetKILLED
A rekey only on the sequence spaceKILLED
Every epoch is the same keyKILLED
Uniqueness ignores the key epochKILLED
Uniqueness ignores the IVKILLED
The IV is not counted on the wireKILLED
The overhead gating is invertedKILLED
Efficiency invertedKILLED
The effective rate is the raw rateKILLED
Overhead blindness reported with no MACKILLED
The correct build protects data onlyKILLED
Addresses never reported exposedKILLED
Control traffic never reported exposedKILLED
The negotiation takes the higher levelKILLED
The floor boundary is off by oneKILLED
The correct build agrees below the floorKILLED
The alarm boundary is off by oneKILLED
A silent drop reported on a delivered flitKILLED
The encryption-only build checks everythingKILLED

19. Verification Strategy

Two builds, one stimulus. The parameter is the only difference, and the "broken" build is always a receiver that omits a check.

Drive each term of every disjunction alone. Section 9's rekey has two triggers and the two mutations reducing it to either one are killed by different rows.

Drive the case where the shortcut is correct. A link with no MAC, where zero overhead is honest. A verifying flit during a run of failures. A repeated IV after a rekey. In each, a checker that fired would fire on a good case.

Distinguish a gap from a replay. Section 7's jump from 2 to 50 is 47 lost flits, and a receiver rejecting it would reject every lossy link.

Assert the mask, not only the summary bit. The one non-equivalent survivor here was exposed_mask, which named which traffic classes were in the clear while nothing read it.

Establish whether a survivor is redundant or dead. Two survivors here were equivalent and benign; batch 018's earlier one was equivalent and pointed at an unreachable branch. The classification matters and the fix differs.

20. Synthesis and Implementation Reality

No cryptography is modelled, and the real cost is where the model stops. A MAC over every flit at line rate is a throughput requirement on the crypto engine, and a design whose engine cannot keep up either stalls the link or does not protect every flit. Which of those it does is a decision that must be explicit.

Key provisioning is outside this chapter and is the hard part. Section 9 says when to rekey and nothing about how the new key is agreed — which requires the authenticated channel of 19.1 and is the reason the two chapters compose in that order.

The overhead of section 11 competes directly with 18.2's ceilings. A 16-byte MAC on a 64-byte payload is a second multiplier on the same raw rate as flit efficiency, and the two compound: a link at 75% flit efficiency and 72% security efficiency delivers 54% of its line rate as payload.

Section 12's selective protection is often not a choice. Addresses may need to be visible to the switch for routing — 16.2 established that a switch must read a destination to forward — so protecting them end-to-end conflicts with forwarding them hop-by-hop. That tension is real and this model does not resolve it; it only makes the exposure visible.

Section 14's alarm threshold needs tuning against the link's error rate. Set too low it fires on ordinary bit errors; too high and an attacker gets a large forgery budget before anybody looks. It is 18.5 section 9's noise-band problem with a security consequence attached.

21. Silicon Observability

ObservableWhy it matters
MAC verification failures, counted not just droppedsection 14 — the difference between noise and an attack
Replay drops, separately from verification dropssection 7 — they indicate different things
Bytes and sequence numbers used under the current keysection 9 — both limits, and either forces a rekey
Rekey events and their triggersection 9 — a rekey nobody expected is a signal
Negotiated security level, per linksection 13 — the configured level is not the achieved one
Which traffic classes are protectedsection 12 — the exposure is a policy decision, and policies drift

The fifth row is the one that decays. A link configured for a security level and negotiated down to a lower one reports the configuration in every inventory and the negotiation nowhere — which is exactly the shape of 17.4 section 9's generation-negotiation problem, in a domain where the consequence is larger.

22. Debug Lab

Symptom: a link is configured as protected and something on it is not behaving as though it were.

Check what the negotiation actually settled on. Section 13: the configured level is a request. If the peer offered less and there is no floor, the link is running at the peer's level and the inventory says otherwise.

Check whether a MAC is present at all, or only encryption. Section 5: an encrypted link with no MAC accepts modified ciphertext and looks identical in every configuration dump.

Check the replay counter. Section 7: a receiver with no sequence check accepts every recorded flit, and every one of them verifies.

Check the sequence space against the rekey interval. Section 9: a link nowhere near its data budget can exhaust a sixteen-bit counter, and a wrapped counter silently disables section 7.

Check MAC verification failure counts. Section 14: if they are not counted, an attacker gets unlimited attempts against section 6's work factor with nothing to see.

Check which traffic classes are in the clear. Section 12: protecting payloads and leaving addresses exposed leaks the access pattern, which for a memory device is most of the information.

Recompute the effective bandwidth. Section 11: 88 bytes on the wire for 64 useful is 27% gone before 18.2's ceilings apply.

23. Design Review

Is there a MAC, or only encryption? They are separate mechanisms and only one detects modification.

How long is the MAC, and what forgery budget does that imply?

Is there a replay counter, and what happens when it wraps?

What are the two rekey limits, and which one binds first on this link?

Is the IV unique within a key epoch, and what generates it?

What does the negotiation floor allow, and can a peer take the link below it?

Which traffic classes are protected, and was leaving the others exposed a decision or a default?

What happens on a verification failure, and does anybody count?

24. How This Appears In Real Engineering

Link-security failures present as links that are configured as protected and are not, with every configuration dump agreeing that they are.

The characteristic case is encryption without integrity. Confidentiality is the property everybody names, the configuration says "encrypted", and modified ciphertext is decrypted and acted on with no indication anything happened.

The second is a negotiated downgrade. The host is configured for the highest level, the peer offers less, there is no floor, and the inventory reports the configured level forever.

The third is a wrapped sequence counter. The link is well within its data budget, the sixteen-bit counter exhausts, and the replay protection built carefully in section 7 stops working without any error.

The fourth is silent drops. Verification failures are dropped correctly and counted nowhere, so an attacker probing the MAC is indistinguishable from a slightly noisy cable.

25. Common Misconceptions

"The link is encrypted, so it is secure." Encryption is confidentiality. Modification, replay, and who is at the other end are three further questions and encryption answers none of them.

"Nobody can read it, so nobody can change it." Ciphertext an attacker cannot read is ciphertext an attacker can still flip bits in. Whether the result is useful depends on the mode; whether it is detected depends on the MAC.

"The MAC verified, so this is a fresh flit." A replayed flit has a genuine MAC over genuine data. Integrity checking cannot detect a replay, which is why the counter is separate.

"We use a strong cipher." With what MAC length? Section 6's 32-bit MAC is 2^31 expected forgeries whatever the cipher is.

"A gap in the sequence numbers means an attack." It means lost flits. Rejecting gaps rejects every lossy link; the check is against the highest seen.

"We rekey on a timer." On bytes and on sequence numbers. A link can exhaust a sixteen-bit counter well inside any time-based interval, and the wrap re-enables every old flit.

"The IV is random so it will not repeat." Over a large enough space, probably. The model's question is what happens when it does, and the answer is that a rekey resets the space — which is why sections 9 and 10 are the same mechanism seen twice.

"We protect the data." And the addresses? For a memory device the access pattern is most of what an observer wants, and it is the class most often left in the clear.

26. Interview Reasoning

Q1. A link is encrypted. What have you established? That an observer cannot read the traffic. Not that it has not been modified, not that it is not a replay, and nothing about who is at the other end.

Q2. Is encryption without a MAC a real configuration? Yes, and it is the dangerous one. An attacker cannot read the traffic and can still change it, and the receiver decrypts whatever arrives.

Q3. Is a MAC without encryption useful? Yes. The traffic is readable and cannot be modified undetected. It is a legitimate trade when confidentiality is not the requirement.

Q4. How long should a MAC be? Long enough that 2^(n−1) forgery attempts is out of reach. 64 bits is 2^63; 32 bits is 2^31, which is a budget rather than an impossibility.

Q5. Can a MAC detect a replay? No. A replayed flit carries a genuine MAC over genuine data and verifies perfectly. Replay needs a counter, and it is a separate mechanism.

Q6. Sequence jumps from 2 to 50. Attack or not? Not — 47 flits were lost. The replay check is against the highest seen, not against the next expected, because rejecting gaps rejects every lossy link.

Q7. Why rekey? Two limits. The data a key protects, and the sequence space that guarantees uniqueness. Either one exhausting forces it.

Q8. What happens when a sequence counter wraps? Every old flit looks new, and the replay protection stops working with no error anywhere. That is why the rekey is bounded by sequence space and not only by bytes.

Q9. Is an IV repeated after a rekey a problem? No. A rekey resets the IV space. Uniqueness is required within a key epoch, and a model forbidding repetition across epochs would forbid the only thing that makes a finite IV space workable.

Q10. What does security cost in bandwidth? At a 64-byte payload with a 16-byte MAC and an 8-byte IV, 27 percent — a 400Gbps link delivers 288 of payload. At an 8-byte payload it is 75 percent.

Q11. You protect payloads and leave addresses in the clear. What leaks? The access pattern — which pages, in what order, how often. For a memory device that is most of what an observer wants, and it is a strong description of what the workload is doing.

Q12. Why must negotiation have a floor? Because without one the link runs at whatever the peer claims to support, and an attacker who can influence that claim chooses the security level.

Q13. Is every downgrade a failure? No. A device that cannot do confidentiality agreeing on integrity is a legitimate outcome if integrity is above the floor. The failure is agreeing below what policy allows.

Q14. What do you do with a flit whose MAC fails? Drop it, and count it. One failure is a bit error; a run of them is an attack signature, and a receiver that drops without counting cannot tell them apart.

Q15. Where should the alarm threshold sit? Above the link's ordinary error rate and below a useful forgery budget. Too low it fires on noise; too high an attacker gets a large number of attempts unobserved.

Q16. Which of the five properties in section 15 is confidentiality? None of them. Encryption is what the link does with the payload once all five hold — it is not a condition and cannot substitute for any of them, which is why the encryption-only build calls six links of six secure.

27. Exercises

1. Extend RTL 1 with a third property — freshness as a first-class flag rather than a consequence of the counter. Does both become all three, and which of section 15's gates does it correspond to?

2. In RTL 2, model a MAC whose verification is attempted at line rate. At what forgery rate does the attempt budget in attempts_k become reachable before the link is rekeyed?

3. RTL 3 uses a single highest-seen value. Model a sliding window that tolerates reordering. What is the largest reordering it can accept without accepting a replay?

4. Using RTL 4 and RTL 3 together, find the byte budget that guarantees a rekey before a sixteen-bit sequence counter can wrap, for a given flit size.

5. In RTL 5, make the IV a counter rather than an input. Which of the uniqueness assertions become structural rather than checked?

6. RTL 6 charges a fixed MAC and IV per flit. Model a scheme that MACs a group of flits together and derive the group size at which the overhead falls below 5 percent.

7. In RTL 7, make addresses protected end-to-end and determine what 16.2's switch would need in order to still route. Is there a construction that satisfies both?

8. Add a sixth property to RTL 10 for 19.1 section 14's re-authentication freshness. Is it independent of key_fresh, and which one expires first?

28. Summary

Authentication established who is on the link; this chapter protects what crosses it.

Integrity and confidentiality are different properties. A cipher without a MAC is a link an attacker cannot read and can still modify, and the receiver acts on whatever arrives.

A MAC is a probability. 64 bits is 2^63 expected forgeries; 32 bits is 2^31, which is a budget somebody can afford.

Replay needs its own counter. Two of five flits were replays, and all five verified — integrity checking cannot detect repetition.

A key has two limits, data and sequence space, and either one alone forces a rekey. A wrapped counter silently re-enables every old flit.

An IV must be unique within a key epoch — and only within it, because the rekey is what makes a finite space workable.

Security costs bandwidth. 88 bytes on the wire for 64 useful: a 400 Gbps link delivering 288, and 75% overhead at an 8-byte payload.

What is left in the clear is a decision. Three of four traffic classes exposed by a data-only policy, including the address stream that describes the workload.

Negotiation must have a floor, or the peer chooses the security level.

And a failed verification must be counted, because one is noise and a hundred is an attack.

Encryption is not one of the five properties a secure link needs. The encryption-only build called six links of six secure, and its criterion — the traffic is unreadable — measures none of them.

19.3 — Isolation takes a link that is authenticated and protected and asks the question a shared pool raises: what stops one host reaching another's memory on a device they both legitimately use.

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.