PDCP-NR in a Real 5G Capture
One layer of the 5G NR attach walkthrough, followed on its own: every PDCP PDU on both of the connection's bearers, and the sequence numbers that tie them together.
๐ก Read the walkthrough and the diagram side by side. This page carries two diagrams โ one per bearer. The signaling bearer's is linked above and walked in Act One; the data bearer's is linked further down, where Act Two begins. Open whichever act you are reading in a split-screen window so the captions stay in view. On macOS, prefer Chrome or Firefox โ Safari has no in-browser split screen.
Where PDCP sits
PDCP appears in both planes of the 5G radio stack, and this page walks one bearer in each โ so it gets both pictures. The layer is the same in either; what changes is what sits above it and where the traffic goes once it leaves the gNB.
Control plane โ the signaling bearer
Under RRC, carrying the signaling that sets the connection up. This is the stack Act One walks on SRB 1.
User plane โ the data bearer
Under SDAP, instead of RRC, carrying user traffic that continues past the gNB to the UPF. This is the stack Act Two walks on DRB 1.
Same layer, two entities. The difference between those two stacks is exactly the difference the rest of this page is about: a 12-bit sequence number and a mandatory integrity tag on one, an 18-bit sequence number and no integrity tag at all on the other.
What PDCP does
PDCP โ Packet Data Convergence Protocol (TS 38.323) is the last layer a packet passes through before it becomes radio traffic, and the first one it passes through coming back. It is where the radio link stops being a transport problem and starts being a security problem.
Everything above PDCP hands down whole messages and assumes they will arrive, once, in order, and unread by anyone else. PDCP is what makes those three assumptions true:
- It numbers. Every
SDU(Service Data Unit โ one packet handed down from RRC or SDAP) gets anSN(Sequence Number). That number is the anchor for everything else the layer does. - It ciphers, and it may integrity-protect. Access-Stratum security lives here. The ciphering algorithm consumes the sequence number, so the numbering and the encryption are the same mechanism seen from two angles.
- It reorders, de-duplicates, and discards. On the receiving side, the sequence number lets PDCP put out-of-order deliveries back in order and drop a packet it has already seen โ which matters, because the layer below is allowed to deliver both.
That last point is the reason PDCP sits above RLC rather than beside it. The two differ in scope, not in diligence: RLC makes delivery reliable across one radio link, retransmitting until the far end confirms; PDCP secures the message and puts it back in order above whatever the link below had to do to move it. Their sequence numbers count different things.
Six fields carry the whole walk, and they are worth learning before it starts:
| Field | Meaning |
|---|---|
SN | Sequence number. It counts SDUs handed to the layer โ not bytes, not transmissions. 12 bits on a signaling bearer; 12 or 18 bits on a data bearer, chosen by configuration. |
COUNT | The 32-bit value the cipher actually consumes: an HFN (Hyper Frame Number) concatenated with the SN (TS 38.323). Only the SN travels; the HFN is state each end keeps and increments when the SN wraps. |
D/C | The Data/Control bit, one bit. It exists only on the user plane โ it distinguishes a PDCP Data PDU from a PDCP Control PDU (a status report or ROHC feedback). Signaling bearers have no such bit, because they never carry a Control PDU. |
MAC-I | Message Authentication Code for Integrity: a 32-bit tag in the trailer, after the payload. Always present on a signaling bearer; present on a data bearer only if integrity protection was configured. |
BEARER / DIRECTION | Two more cipher inputs alongside COUNT and the key: which bearer, and which way. Together they guarantee that two PDUs never share a keystream. |
Those fields do not share one layout. TS 38.323 ยง6.2 defines a separate PDU format per bearer type and per sequence-number width, and the two this capture uses are the two drawn below.
The signaling bearer's header is the smallest thing PDCP defines โ four reserved bits, twelve bits of sequence number, and nothing else (ยง6.2.2.1). There is no D/C bit at all, because an SRB has no Control PDU to tell it apart from a Data PDU.
Frame 4 reads exactly that shape: 0000 .... = Reserved: 0, then .... 0000 0000 0000 = Seq Num: 0.
The data bearer runs an 18-bit sequence number, which needs a third octet and spends the very first bit on D/C (ยง6.2.2.3):
Frame 41 reads 1... .... = PDU Type: Data PDU and then .000 00.. = Reserved: 0x00 โ the D/C bit set to Data, then those five reserved bits. A DRB configured for a 12-bit sequence number instead (ยง6.2.2.2) keeps the D/C bit but drops back to two octets, leaving three reserved bits where the SRB has four; frame 38 selects len18bits on this bearer, so that third format never appears in the trace.
One format remains, and this capture never produces it. A PDCP Control PDU carries no SDU at all โ it is PDCP talking to its own peer rather than to the layer above (ยง6.2.3.1). D/C is zero, and a 3-bit PDU type selects between a status report (000) and interspersed ROHC feedback (001). The status report names an FMC (First Missing COUNT) and then a bitmap covering what came after it:
That format is why the D/C bit exists, and why only the user plane has one. Act Two comes back to it: frame 38 arms this bearer to send status reports, and not one is ever sent.
One thing to note: the PDCP header is never ciphered. Ciphering starts immediately after it and covers the payload and the MAC-I trailer (TS 38.323 ยง5.8). A gNB has to be able to route, reorder, and de-duplicate PDUs before it decrypts them, so the sequence number stays in the clear on every frame โ even the frames in this trace that nobody has the keys for.
This page is about the frame-by-frame mechanics: the number, the COUNT, the tag, and the boundary. The security story โ the three encryption levels in this capture, the key hierarchy, and how the trace was opened in the first place โ belongs to Decrypting a 5G NR radio capture, and this walk links back to it wherever the two touch.
Two bearers, two PDCP entities
One UE. One radio connection with two completely independent PDCP entities.
The trace carries an SRB (Signaling Radio Bearer) for control messages and a DRB (Data Radio Bearer) for user traffic, and both are numbered 1. They are not two halves of one story. They have different header formats, different keys, and โ the point of this page โ separate sequence-number and COUNT spaces:
| SRB 1 | DRB 1 | |
|---|---|---|
| Session | pdcp-bearer/timeout/00005 | pdcp-bearer/timeout/00012 |
| Plane | 1 (Signalling) | 2 (User) |
| Messages | 26 | 32 |
| Frames | 4โ146 | 41โ114 |
| Sequence-number width | 12-bit | 18-bit |
D/C bit | absent | present, always Data PDU |
MAC-I | present on all 26 | absent on all 32 |
| Ciphering key | 95F23667A60D91689B31772783E6FDDD | 4CB12A7FB40AE866AE59FC9529E0BC5B |
| Diagram | Act One, below | Act Two, below |
๐ก Where these diagrams come from. The Session names in that table are how VisualEther โ the tool that decoded this capture and generated the diagrams here โ labels each per-bearer slice when it splits the trace into sessions.
That is why this page carries two diagrams instead of one timeline. A sequence number means nothing across the boundary, and neither does a COUNT: SRB 1's SN=5 and DRB 1's SN=5 are unrelated packets that were ciphered with different keys.
There is a second, finer split inside each bearer. Each end runs its own PDCP entity and keeps its own TX_NEXT for what it transmits (TS 38.323 ยง7.1), so the uplink SN=0 and the downlink SN=0 on the same bearer are also unrelated โ they were minted by different entities. Four independent counters open these two diagrams.
Two facts are true of every PDU on both diagrams, and they are worth stating once rather than repeating them on both:
- COUNT never differs from
SN. Wireshark shows the cipher's COUNT input on 16 of the 26 signaling PDUs, and on all 32 data PDUs, and on every one of them it is identical to the sequence number in the header. The HFN is zero throughout โ nothing in this capture runs long enough to wrap a counter. - There is not one PDCP Control PDU in the entire file. The
D/Cbit takes exactly one value, Data PDU, wherever it appears. No status report, no ROHC feedback โ which, as Act Two explains, is exactly what the configuration predicts.
Act One โ SRB 1, the signaling bearer
26 messages, frames 4 to 146: 12 uplink PDUs and 14 downlink PDUs, 12-bit sequence numbers, a four-byte MAC-I on every one. This is the diagram linked at the top of the page. It is the bearer that teaches the mechanism, because it is the only one where you can watch the security switch on.
Frame 4 โ the whole SRB header format in two bytes. The first PDCP PDU of the capture reads 0000 .... = Reserved: 0 and then .... 0000 0000 0000 = Seq Num: 0. Four reserved bits, twelve bits of sequence number, and that is the entire header. There is no D/C bit here โ the signaling PDU format has no way to express a Control PDU (TS 38.323 ยง6.2.2.1).
Behind the SDU sits the four-byte MAC-I trailer, and Wireshark reads it as MAC: 0x00000000 [Matches calculated result]. Access-Stratum security has not been activated yet, and TS 38.323 ยง6.3.4 says the field is still present on an SRB and padded with zeros until it is. Eight PDUs in this session carry a zeroed MAC-I: frames 4, 7, 9, 11, 12, 14, 15, and 133.
Frame 7 โ the downlink has its own counter. The gNB's first PDU is also Seq Num: 0. Not a repeat of frame 4; the other direction's entity opening its own count.
Frame 12 โ frame carrying the encrypted NAS packet. Uplink SN=2. At the PDCP layer, this PDU is wide open: no ciphering yet, MAC-I all zeros. At the NAS layer, it is completely opaque โ security header type Integrity protected and ciphered with new 5GS security context (4), message authentication code 0x97f62856, and then Encrypted data.
An unciphered PDCP PDU whose payload is still unreadable. The NAS layer runs its own security context, negotiated with the core rather than the gNB, and it started well before this one. The decryption companion has the full account of the split; the thing to take from this frame is that the two layers are genuinely independent, and you can see it in a single packet.
Frames 17 to 23 โ where security actually starts
Frame 17 is the RRC Security Mode Command. Downlink SN=3, carrying a securityModeCommand that selects cipheringAlgorithm: nea2 (2) and integrityProtAlgorithm: nia2 (2) โ AES for both. (The RRC companion reads the message itself; this page is about what PDCP then does with it.) Two things change here, and they change at different moments.
The MAC-I is suddenly real: 0x5cfaa560, not zeros. Integrity protection applies to this very message, with the new key.
But the message is still readable. Ciphering is not applied to it. TS 38.331 ยง5.3.4.3 draws the line exactly there โ integrity from this message onward, ciphering only after the procedure completes โ and the trace shows it plainly: the RRC decodes in full and Wireshark's Deciphered Data field is absent, because nothing had to be decrypted.
Wireshark does flag MAC-I Digest wrong - calculated 00000000 but found 5cfaa560 here, and that is a tooling artifact rather than a protocol error: the dissector only learns the algorithms from this frame, so it validated the digest before it had them. Every subsequent PDU of this connection โ on both bearers, including all 32 on the data bearer that does not exist yet โ names this frame as its Configuration frame: 17.
Frame 18 is the Security Mode Complete, and the mirror image. Uplink SN=4, MAC-I 0x944c9d98 โ a real digest โ and again no Deciphered Data. Integrity yes, ciphering not yet.
It is also the first frame where Wireshark prints the complete set of inputs the cipher will use for the rest of the connection:
frame : Frame 18: Packet, 691 bytes on wire (5528 bits), 691 bytes captured (5528 bits)
eth : Ethernet II, Src: 00:00:00:00:00:00, Dst: 00:00:00:00:00:00
Destination : 00:00:00:00:00:00
Source : 00:00:00:00:00:00
ip : Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Differentiated Services Field : 0x00 (DSCP: CS0, ECN: Not-ECT)
010. .... = Flags : 0x2, Don't fragment
udp : User Datagram Protocol, Src Port: 13337, Dst Port: 0
Timestamps
mac-nr : MAC-NR UL-SCH (LCID:1 3 bytes) || (LCID:1 10 bytes) (Short BSR LCG ID=0 BS=0) (PHR PH=57 PCMAX_f_c=52) (Padding 601 bytes)
Context (RNTI=32768)
Subheader : (LCID:1 3 bytes)
RLC-NR UEId=1 [UL] [AM] SRB:1 [CONTROL] ACK_SN=4
Context
AM Header ACK_SN=4
Subheader : (LCID:1 10 bytes)
RLC-NR UEId=1 [UL] [AM] SRB:1 [DATA] (P) SN=4 [8-bytes]
Context
AM Header (P) SN=4
PDCP-NR (SN=4 )
Configuration : UEId= 1 SRB-1 (direction=Uplink, plane=Signalling)
UE Security (ciphering=NEA2 (AES), integrity=NIA2 (AES))
Sequence Analysis - OK
NR Radio Resource Control (RRC) protocol
UL-DCCH-Message
message : c1 (0)
c1 : securityModeComplete (5)
securityModeComplete
criticalExtensions : securityModeComplete (0)
securityModeComplete
Subheader : (Short BSR LCG ID=0 BS=0)
Subheader : (PHR PH=57 PCMAX_f_c=52)
Subheader : (Padding 601 bytes)
Frame 18's field tree, opened at MAC-NR. Expand along the path to reach the cipher's input set โ mac-nr โ RLC-NR โ PDCP-NR โ UE Security โ where the algorithms, BEARER, DIRECTION, COUNT, and the key sit. Or expand the RRC node under PDCP-NR to see the SecurityModeComplete it is protecting.
COUNT: 4 is the number to look at. COUNT is 32 bits โ an HFN concatenated with the sequence number โ and only the sequence number travels on the wire. Here the SN has not wrapped, so COUNT and SN read the same, and they do so on every PDU in both sessions.
The split depends on the sequence-number width, because the two always total 32 bits. A 12-bit bearer spends 20 of them on the HFN:
An 18-bit bearer takes six of those bits back, leaving a 14-bit HFN:
BEARER: 0 and DIRECTION: Uplink (0) are the other two inputs, and they are what make the numbering safe. Uplink SN=4 and downlink SN=4 on this bearer produce different keystreams because DIRECTION differs; SRB 1's SN=4 and DRB 1's SN=4 produce different keystreams because the keys differ. Change any one input and the output changes completely. The decryption companion has the key hierarchy those two keys descend from.
Put the five together and the whole of ciphering is one block. TS 33.501 ยงD.2 feeds 128-NEA2 a 128-bit KEY, the 32-bit COUNT, a 5-bit BEARER, a 1-bit DIRECTION, and the length of keystream wanted; out comes a keystream block that is XORed with the plaintext:
Two things follow from that picture, and both show up in this capture. Only the plaintext side is secret, so the header outside the block stays readable to anyone. And because the block is deterministic, frames 128 and 129 โ same key, same COUNT, same bearer, same direction โ could not have produced anything but byte-identical ciphertext.
Integrity is the same shape with a different output (ยงD.3): 128-NIA2 takes the key, COUNT, BEARER, DIRECTION, and the message, and returns the 32-bit MAC-I rather than a keystream. That is why the tag changes when any one of them changes, and why a replayed message cannot borrow another frame's digest.
Frame 20 is the first ciphertext on the bearer. Downlink SN=4, and a Deciphered Data field appears for the first time in the capture, holding 300201200100100038426d05. Click the frame 20 message in the interactive viewer at the top of this page to open its field tree: MAC-NR -> RLC-NR -> PDCP-NR -> Deciphered Data. The frame 18 tree above has no such node โ nothing needs decrypting yet. Look at how it ends โ 38426d05 โ and compare it with the frame's MAC: 0x38426d05.
The MAC-I is inside the ciphered region. TS 38.323 ยง5.8 puts both the data part and the MAC-I under the cipher, so an observer without keys cannot see the integrity tag either. Only the header stays in the clear.
Frame 23 โ one sequence number, 1667 bytes, three RLC transmissions. Uplink SN=5 carries the UECapabilityInformation, and Wireshark reassembles it to 1667 bytes. It occupies exactly one PDCP sequence number. PDCP numbers the SDU it was handed; how many pieces the scheduler forced RLC to cut it into is invisible from up here. The RLC companion walks the same event from below, as a three-segment run across frames 21 to 23.
Frame 38 โ the hinge
Downlink SN=6 is an RRC Reconfiguration, and its drb-ToAddModList adds DRB 1 with a pdcp-Config that decides everything the second diagram shows:
| Setting | Value |
|---|---|
pdcp-SN-SizeUL / pdcp-SN-SizeDL | len18bits (1) |
discardTimer | infinity (15) |
integrityProtection | not present |
headerCompression | notUsed (0) |
statusReportRequired | true (0) |
t-Reordering | not present |
integrityProtection is NOT present is the one to remember. It is why every PDU on the data bearer arrives with MAC-I Present: False.
The same message carries an sdap-Config โ sdap-HeaderUL: present (0), sdap-HeaderDL: absent (1), one mapped QoS flow with QFI: 2 โ and adds SRB 2 with pdcp-Config is NOT present. No frame in this capture ever carries a pdcp-Config for any SRB. SRB 1 runs the format the spec fixes for signaling bearers, and nothing in the trace configures it.
Frames 39 to 128 โ a 10340.792 ms silence. Uplink SN=8 returns the RRCReconfigurationComplete; its deciphered payload is 0800b04f2105 โ two bytes of RRC, then b04f2105, which is exactly what the MAC field displays. Then the signaling bearer goes quiet for more than ten seconds while the entity frame 38 just created does the actual work. That silence is Act Two.
Frames 128 and 129 โ a retransmission that reuses a COUNT, legitimately
Frame 128 is downlink SN=7, continuing directly from the SN=6 of frame 38 ten seconds earlier. The entity kept its full state through the silence. It deciphers to 1000a48652fc: an RRC Release and the MAC-I 0xa48652fc.
Frame 129 is the same PDU again, 44.894 ms later, byte for byte. Wireshark heads the block Sequence Analysis- SN 7 Repeated and raises PDCP SN (7) repeated for Downlink for UE 1 (DCCH-1), with Expected SN: 8 and OK: False. The deciphered data is 1000a48652fc, and the MAC-I is 0xa48652fc โ identical to frame 128 in both cases.
That identity is the lesson. PDCP has no retransmission machinery at all. What happened is that RLC's poll went unanswered, its poll-retransmit timer expired, and RLC put the same stored PDU back on the wire โ the RLC companion measures that timer off exactly this pair of frames. Because PDCP had already assigned COUNT 7 and ciphered under it, the ciphertext could not change.
TS 33.501 forbids reusing a COUNT with the same key, bearer, and direction for different plaintext, because that reuses keystream. Re-sending an identical PDU reuses nothing new. Which gives the practical rule: a repeated PDCP SN with identical ciphertext is a lower-layer retransmission; a repeated PDCP SN with different ciphertext would be a genuine security incident.
Act Two โ DRB 1, the data bearer
Now rewind. While the signaling bearer sat silent, the entity frame 38 created was carrying the traffic: 32 messages, frames 41 to 114 โ 18 uplink PDUs numbered 0 to 17, and 14 downlink PDUs numbered 0 to 13. Its own diagram, its own counters, its own key.
Frame 41 โ a different header shape entirely. Seq Num: 0, and everything around it has changed:
1... .... = PDU Type: Data PDUโ theD/Cbit, appearing for the first time in the capture. It exists only on the user plane, because only a DRB can carry a PDCP Control PDU..000 00.. = Reserved: 0x00โ five reserved bits rather than four.Seqnum length: 18, so the header is three bytes rather than two.MAC-I Present: Falseโ no integrity trailer at all, the direct consequence of frame 38'sintegrityProtection is NOT present. This bearer is ciphered but not integrity protected, which is the ordinary configuration for user data.
And one subtle field: SDAP header: Present, QFI: 2. TS 38.323 ยง5.8 excludes the SDAP header from ciphering even though it rides inside the PDCP SDU, and the trace bears it out โ Wireshark's Deciphered Data for this frame begins 6000..., the IPv6 version nibble, with the SDAP byte outside it. The QoS Flow Identifier has to stay readable so the receiver can classify a packet it has not yet decrypted.
Frame 43 โ the same bearer, a different PDU layout. Downlink SN=0 reports SDAP header: Not Present. Not an inconsistency: frame 38 said sdap-HeaderUL: present (0) and sdap-HeaderDL: absent (1), so the two directions genuinely carry different layouts. The ignorance runs one way. The gNB already knows which flow it is sending on, because the QFI arrived with the packet from the UPF, so repeating it to the UE would say nothing new. Going up, it is the gNB that has to be told โ it must name the flow again before handing the packet to N3, and the header is the only thing that can name it. The SDAP companion has the full argument. Across the session, QFI: 2 appears on all 18 uplink PDUs and on none of the 14 downlink ones.
Frames 50 to 53 โ the counter versus the transmissions. Frame 50 is three RLC PDUs on the wire but only one complete PDCP PDU, SN=2. Frame 52 completes SN=3, reassembled to 1264 bytes from three RLC segments. Frame 53 completes SN=4, reassembled to 514 bytes. SN 3 and SN 4 were in flight simultaneously โ frame 52 carried the tail of one and the head of the other. That interleaving is exactly why PDCP numbers SDUs before handing them down.
Frames 72 onward โ a third layer of encryption, inside the plaintext. Uplink SN=8 deciphers not to TCP but to IPv6 next header 50: ESP, IPsec's Encapsulating Security Payload, with SPI 0x00000100. We decrypted PDCP successfully and found more ciphertext underneath, protected by keys that were never on this radio link. It is frame 12's lesson again in a different place โ PDCP protects one hop, and it is not the only thing protecting this traffic. The decryption companion follows that payload the rest of the way and explains why the trail ends there.
Frames 90 and 110 โ segmentation is invisible from up here. Downlink SN=8 is a 1223-byte PDCP PDU carried whole. Downlink SN=11 is a 1499-byte PDU that RLC had to cut in two. Same bearer, same direction, same layer โ the only difference is how much room the scheduler happened to offer. PDCP's numbering is unaffected either way, which is the whole point of the boundary.
Frames 97 and 111 โ two PDCP PDUs in one frame. Frame 97 completes uplink SN=14 and carries the whole of SN=15; frame 111 does the same for downlink SN=12 and SN=13. Two sequence numbers, two COUNT values, two separate keystreams, one radio transmission. The diagram splits each pair into two arrows because they are two independent PDUs.
Frame 114 โ the bearer's last PDU. Uplink SN=17, reassembled to 984 bytes. Eighteen uplink PDUs numbered 0 through 17 with no gap and no repeat; Sequence Analysis - OK on every one of the session's 32 PDUs, and not a single retransmission.
The contrast with Act One is instructive, and it is not about PDCP. PDCP has no retransmission logic on either bearer. The difference is that every RLC poll on this bearer was answered, so nothing was ever re-sent, so no COUNT was ever used twice.
One more thing frame 38 predicted, and the trace confirms: statusReportRequired: true (0) arms this bearer to send a PDCP status report โ and none is ever sent, in either direction, in the whole capture. A PDCP status report is a re-establishment artifact, and frame 38 also says reestablishPDCP is NOT present and recoverPDCP is NOT present. Nothing ever asked for one.
The later connections
The signaling bearer's diagram does not stop at frame 129. Frames 133 to 146 are a second RRC connection, 3225.427 ms later, and Wireshark's configuration line switches from UEId= 1 to UEId= 2.
Everything resets. Uplink Seq Num: 0 on SRB 1 again, MAC: 0x00000000 [Matches calculated result] again, and no Previous frame for Bearer link back to frame 129. A PDCP entity lives and dies with its bearer, so TX_NEXT, the COUNT state, and the security context all start from nothing. From there, the second connection repeats the first in miniature โ three uplink PDUs numbered 0 to 2, five downlink PDUs numbered 0 to 3 with the last one repeated.
That repeat is frames 145 and 146, 44.915 ms apart, and it is frame 129 all over again: PDCP SN (3) repeated for Downlink for UE 2 (DCCH-1), OK: False, and the same two bytes on the wire both times. This SRB session ends there, mid-retransmission โ not the capture.
A third connection begins at frame 150, outside this session โ the gap before it is past the timeout that closes the session, so it appears on neither diagram.
Where ciphering starts, measured twice โ once with keys and once without
Frames 17 and 18 showed the boundary that TS 38.331 ยง5.3.4.3 defines: integrity protection from the Security Mode Command onward, ciphering only after the procedure completes. On the first connection, you can watch it happen because the capture ships with that UE's Access-Stratum keys.
The second connection is the control experiment, and it is better evidence. There are no keys for UEId 2 anywhere in this trace. Nothing on that connection can be decrypted. And yet:
| Frame | Message | What Wireshark shows |
|---|---|---|
| 133 | RRCSetupComplete | Decodes fully. MAC: 0x00000000 |
| 136 | RRC securityModeCommand | Decodes fully. Real MAC-I 0xcc0cdfbc, and the same MAC-I Digest wrong artifact as frame 17 |
| 137 | RRC securityModeComplete | Decodes fully. Real MAC-I 0x78b22a09 |
| 139 | first message after the procedure | Signalling Data: 38a4bc1a51d9573b91b80215131c5150... โ opaque |
| 140, 142, 145, 146 | everything after | opaque |
Read those five rows together. On a connection nobody holds a key for, the last two messages that stay readable are the two that bracket security activation โ and the very next PDU goes dark. Wireshark's pdcp-nr.signalling-data field, the one it falls back to when it cannot decrypt, appears on frames 139, 140, 142, 145 and 146 and on no others.
Now put that beside the first connection. There, Deciphered Data โ the field that appears only when Wireshark actually ran AES โ is absent on frames 4 through 18 and first appears on frame 20 in the downlink and frame 23 in the uplink, immediately after the Security Mode exchange. The boundary sits in precisely the same place on both connections.
That is the same spec rule visible from two directions. With keys, you see the first frame that needed decrypting. Without keys, you see the first frame that could not be read โ and it is the same frame in the procedure. The rule is not an artifact of holding the keys; the keys change which side of it you can see.
Two things this is not, both worth stating because they are the usual misreadings:
- The Security Mode Command is not unprotected. It carries a real MAC-I on both connections,
0x5cfaa560and0xcc0cdfbc. Integrity is already on. It is only ciphering that has not started. - The zeroed MAC-I earlier in each connection is not a failure. Frames 4, 7, 9, 11, 12, 14, 15, and 133 read
0x00000000 [Matches calculated result], which is TS 38.323 ยง6.3.4 doing exactly what it says: the field stays present on an SRB. It is padded with zeros until integrity protection is configured.
If you take one diagnostic habit from this page, take this one. When an SRB stops decoding partway through a trace, do not assume corruption or a dissector bug โ look for the Security Mode Command a frame or two earlier. Everything before it is readable by design, and everything after it needs a key.
Takeaways
- The sequence number counts messages, not transmissions. One PDCP
SN=5covered a 1667-byte capability report that RLC split three ways. Across the whole capture, 59 PDCP PDUs on 57 frames, the PDCP sequence number matched the RLC sequence number of the PDU carrying it every single time โ two counters that happen to run in lockstep because nothing here ever disturbed either one. - COUNT is what the cipher consumes, and
SNis only its lower half. Wireshark prints it on 16 of the signaling bearer's 26 PDUs and on all 32 of the data bearer's, and it is never different from the sequence number, because no counter here wrapped. On a longer trace, the HFN is exactly what you would be hunting when the two diverge. - The header is in the clear; the payload and the MAC-I are not. Frame 20's deciphered bytes end in the same value the
MACfield displays โ the integrity tag lives inside the ciphered region. Everything a receiver needs before decryption โ sequence number,D/Cbit, SDAP header โ is deliberately outside it. - A repeated PDCP SN is usually a lower-layer retransmission. Frames 128/129 and 145/146 re-sent byte-identical PDUs under an unchanged COUNT, 44.894 ms and 44.915 ms apart. Check whether the ciphertext changed: identical means RLC re-sent; different would mean keystream reuse.
- The two bearers share a radio link and almost nothing else. Different sequence-number widths, different header layouts, different keys, and one of them has no integrity tag at all โ all of it decided by a single
pdcp-Configin frame 38.
Where this sits in the stack
This page follows one layer of a much larger trace. The layers around it tell different parts of the same story:
- A 5G NR Attach on the Air Interface, Layer by Layer โ the full walkthrough this article is a slice of: random access through to two mobile-terminated returns, all six layers on one timeline.
- SDAP: QoS flows, the QFI, and the data radio bearer โ the layer directly above, on the data bearer only. It is the one byte frame 41's
Deciphered Datastarts just past, and the reasonQFI: 2shows up on 18 uplink PDUs and no downlink ones. - RLC-NR Acknowledged Mode: sequence numbers, polls, and retransmission โ the layer directly below. Every PDCP PDU on this page became one RLC SDU there, and the retransmissions at frames 129 and 146 are RLC's doing, measured on RLC's own timer.
- MAC-NR: scheduling and multiplexing โ two layers down, and the one that decides the grants. Whether a PDCP PDU traveled whole or in three pieces was settled there.
- Decrypting a 5G NR radio capture โ the conceptual companion to this page: the three encryption levels stacked in this trace, the Access-Stratum key hierarchy the two keys above descend from, and what the user plane turned out to be once PDCP was opened.
Try it on your own capture
Every arrow in both diagrams was decoded and captioned by VisualEther from a raw Wireshark PCAP โ including the session split that separated the two PDCP entities onto their own timelines. Point it at your own 5G, LTE, or IMS trace and read it the same way.