AS Security Mode in 5G NR
Activating access-stratum ciphering and integrity via the Security Mode Command.
AS security is the layer that makes everything else on the radio interface trustworthy, and it is switched on by exactly one exchange: SecurityModeCommand and SecurityModeComplete on SRB1. This document is the engineering detail behind that exchange. The full key hierarchy from the USIM's K down to the four AS keys, and which node holds each one. What is protected on which bearer, and what is not protected at all. The ordering rules -- the command is integrity protected but not ciphered, the complete is both, downlink ciphering starts after the command is sent and uplink after the complete is received -- which is the single most common interop failure in AS security and gets its own section and its own ladder. Algorithm identifiers and how the gNB picks one. The MAC-I inputs and the 16-bit shortMAC-I that gates re-establishment and resume. PDCP COUNT, why reuse under one key is catastrophic, and the counter check that detects divergence. NH, NCC, and vertical versus horizontal derivation at handover. Key change on the fly, re-keying by intra-cell handover, Rel-16 user-plane integrity, the NULL algorithms, security in EN-DC and NR-DC -- and a failure-modes table written around what each fault actually looks like in a log.
Contents
- 01Why AS Security Exists, and the NAS / AS Split
- 02The 5G Key Hierarchy, from K to the Four AS Keys
- 03What Is Protected, on Which Bearer, by Which Key
- 04The AS Security Mode Command Procedure
- 05The Ordering Rules: Where Ciphering Starts in Each Direction
- 06Algorithm Identifiers, and How the gNB Chooses
- 07SecurityModeFailure, and the Failure With No Message
- 08Integrity Protection: the MAC-I and Its Five Inputs
- 09The shortMAC-I: 16 Bits That Gate Re-establishment and Resume
- 10PDCP COUNT, Key Stream Reuse, and the Counter Check
- 11Key Derivation at Handover: NH, NCC, Vertical and Horizontal
- 12Key Change on the Fly, and Re-keying Without Moving
- 13User-Plane Integrity Protection, and Why Rel-15 Left It Optional
- 14The NULL Algorithms and the Emergency-Call Case
- 15Security in EN-DC and NR-DC: S-K_gNB, SRB3, keyToUse
- 16Parameter, IE and ASN.1 Reference
- 17Failure Modes
- 18Illustrative Message Traces
- 19Release Deltas: Rel-15 to Rel-18
- 20Reading AS Security in Logs: A Checklist
- 21Glossary
- 22References
1. Why AS Security Exists, and the NAS / AS Split
Everything a UE and a gNB say to each other after RRCSetupComplete is sensitive. The measurement reports reveal where the UE is. The RRCReconfiguration messages decide which cell it goes to next. The NAS messages relayed on SRB2 carry the subscriber's identity and the session management that pays for it. And the user plane is, of course, the whole point. None of that can be left on an open radio interface, and the mechanism that closes it is AS security -- integrity protection and ciphering performed by the PDCP entities at both ends of the air interface TS 33.501 cl. 6.5.
AS security is not the only layer. 5G runs two independent security contexts, deliberately, and the reason is that they protect different hops with different trust assumptions.
| NAS security | AS security | |
|---|---|---|
| Protects | Signalling between UE and AMF | RRC signalling and user-plane data between UE and gNB |
| Terminates at | AMF, in the core network | gNB -- which in a shared or leased RAN may not be the operator's own equipment |
| Root key | K_AMF | K_gNB, itself derived from K_AMF |
| Keys | K_NASint, K_NASenc | K_RRCint, K_RRCenc, K_UPint, K_UPenc |
| Activated by | NAS SECURITY MODE COMMAND / COMPLETE TS 24.501 cl. 5.4.2 -- companion 01 Registration Process | RRC SecurityModeCommand / SecurityModeComplete TS 38.331 cl. 5.3.4 -- this document |
| Algorithms | 5G-EA0..3 and 5G-IA0..3, chosen by the AMF | NEA0..3 and NIA0..3, chosen by the gNB -- the two layers may pick differently |
| Lifetime | Survives idle periods and gNB changes; re-keyed only on re-authentication or AMF change | Re-keyed at every handover, at every resume, and on demand |
| Counter | NAS COUNT, per direction, per NAS connection | PDCP COUNT, per direction, per bearer (§10) |
Table 1. The two layers. The row that matters architecturally is the second: NAS security exists precisely so that a compromised gNB cannot read NAS signalling, which is why NAS messages relayed on SRB2 are protected twice.
Ordering between the two layers is fixed and worth internalising. NAS security is always activated first, because K_gNB is derived from K_AMF and the uplink NAS COUNT -- values that only exist once NAS security has run. An AS SecurityModeCommand therefore cannot be the first security event in a UE's life, and if you see one on a UE with no prior NAS security establishment in the log, you are looking at either a context that was restored (resume, or handover) or a bug.
What triggers the AS procedure is narrow: the gNB runs it once, immediately after it receives the NGAP INITIAL CONTEXT SETUP REQUEST that carries K_gNB and the UE's security capabilities TS 38.413 cl. 8.3.1. It is not repeated. Every subsequent change of AS keys -- handover, resume, key change on the fly, re-keying -- reuses the existing context and signals the change inside RRCReconfiguration or RRCResume instead (§11, §12). There is exactly one SecurityModeCommand per RRC connection, and a second one in a log means the connection was released and rebuilt.
Two consequences follow, and both are exploited by the design. First, there is an unavoidable window -- RRCSetupRequest, RRCSetup, RRCSetupComplete -- in which nothing on the air is protected at all. This is why the UE sends a SUCI rather than a SUPI, and why the pre-security messages are specified to carry as little as possible (companion 13 RRC Overview). Second, because AS security is activated once and then chained forward through key derivations, the integrity of the whole chain rests on the UE having correctly verified one 32-bit MAC-I on one message. §8 is about that MAC-I.
2. The 5G Key Hierarchy, from K to the Four AS Keys
Every AS key in the system traces back to one 128-bit or 256-bit secret that exists in exactly two places: the USIM and the home network's UDM. Between that secret and the key that ciphers a downlink PDCP PDU there are six one-way derivations, each performed with the same HMAC-SHA-256 based KDF TS 33.501 Annex A and distinguished only by a function code and its input parameters.
K_gNB extracted from one compromised base station reveals nothing about K_AMF, so it cannot be used at any other gNB, on any other connection, or after the next re-key.| Key | Derived from | Freshness input | Held by | Lifetime |
|---|---|---|---|---|
| K | -- | -- | USIM and UDM only | Permanent. Never transmitted, never derived from anything. |
CK, IK | K in the authentication vector | RAND | USIM / ARPF, transiently | One authentication run. In 5G-AKA they are immediately consumed to produce K_AUSF. |
K_AUSF | CK || IK (5G-AKA) or the EMSK (EAP-AKA') | Serving network name | UE and AUSF (home network) | Survives serving-network change; the anchor for SoR and UE parameter update. |
K_SEAF | K_AUSF | Serving network name | UE and SEAF (in the AMF) | One serving network. Discarded when the UE moves to another PLMN. |
K_AMF | K_SEAF | SUPI and the ABBA parameter | UE and AMF | Until re-authentication, AMF change with re-keying, or a NAS key change. Survives idle periods. |
K_gNB | K_AMF | Uplink NAS COUNT | UE and the serving gNB | One gNB, one RRC connection, until the next re-key or handover. |
NH | K_AMF and the previous NH (or the initial K_gNB) | the previous chain element | UE, AMF, and the gNB the AMF gave it to | One hop. Consumed by the handover that uses it (§11). |
K_RRCint | K_gNB | algorithm type 0x04 + integrity algorithm identity | UE and gNB (the CU, in a split architecture) | Until any re-derivation of K_gNB, or an algorithm change. |
K_RRCenc | K_gNB | algorithm type 0x03 + ciphering algorithm identity | UE and gNB-CU | As above. |
K_UPint | K_gNB | algorithm type 0x06 + integrity algorithm identity | UE and gNB-CU (user-plane part) | As above. Only used on DRBs that have integrity configured (§13). |
K_UPenc | K_gNB | algorithm type 0x05 + ciphering algorithm identity | UE and gNB-CU (user-plane part) | As above. |
Table 2. Who holds what. The fourth column is the one to read when reasoning about a compromise: only the last four rows exist inside the gNB, and only K_gNB and NH connect it to anything the core holds.
The four AS keys differ only in the 8-bit algorithm-type distinguisher fed to the KDF alongside K_gNB and the chosen algorithm's identity TS 33.501 Annex A.8. Two consequences follow directly. Changing the ciphering algorithm changes K_RRCenc and K_UPenc even though K_gNB is untouched -- which is why an algorithm change is a re-keying event and cannot be applied to a running bearer without a PDCP re-establishment. And K_RRCint and K_UPint are different keys even when both use NIA2, so a UE that computes a user-plane MAC-I with K_RRCint fails every check while its RRC signalling stays perfectly healthy.
K_gNB deserves a closer look because its freshness input is unusual. It is the uplink NAS COUNT TS 33.501 Annex A.9 -- the counter the UE and AMF maintain for NAS integrity. Using it means K_gNB is bound to a specific point in the NAS signalling stream, so two RRC connections established from the same K_AMF at different times get different K_gNB values without any additional nonce exchange. It also means that the AMF and the UE must agree exactly on that COUNT: an off-by-one, which happens when a NAS message is retransmitted and the two ends disagree about whether it counted, produces two different K_gNB values and hence four different AS keys. The observable symptom is a MAC-I failure on SecurityModeCommand at the UE and a SecurityModeFailure on the wire (§7), with nothing wrong on the radio at all.
3. What Is Protected, on Which Bearer, by Which Key
Protection in NR is a property of the PDCP entity. That single sentence answers most of the questions people ask about what is covered: if a message travels through a PDCP entity that has security configured, it is protected; if it does not travel through PDCP at all, it is not, on any release, under any configuration.
RRCReestablishmentRequest needs the shortMAC-I of §9 carried inside the message instead.| Bearer | Integrity | Ciphering | Keys used | When protection begins |
|---|---|---|---|---|
| SRB0 (CCCH) | Never | Never | -- | Never. RRCSetupRequest, RRCSetup, RRCReestablishmentRequest, RRCResumeRequest and RRCReject are all sent in the clear. |
| SRB1 (DCCH) | Mandatory once active | Mandatory once active, unless NEA0 | K_RRCint, K_RRCenc | Integrity from the SecurityModeCommand itself; ciphering per the asymmetric rule in §5. |
| SRB2 (DCCH, NAS transport) | Mandatory | Mandatory unless NEA0 | K_RRCint, K_RRCenc | SRB2 is only ever established after AS security activation TS 38.331 cl. 5.3.5.6.3, so it is protected from its first PDU. |
| SRB3 (direct to the SN) | Mandatory | Mandatory unless NEA0 | SCG K_RRCint, K_RRCenc from S-K_gNB | From establishment. EN-DC and NR-DC only (§15). |
| DRB, MN-terminated | Only if integrityProtection is configured for that DRB | Yes, unless cipheringDisabled is set | K_UPint, K_UPenc from K_gNB | From the moment the DRB is set up, which is always after activation. |
| DRB, SN-terminated | As above, per DRB | As above | K_UPint, K_UPenc from S-K_gNB | From setup. keyToUse in SecurityConfig selects which root (§15). |
| RLC / MAC / PHY | Never | Never | -- | Never. RLC status reports, every MAC CE, and all physical-layer signalling are unprotected. |
Table 3. The protection matrix. The last row is the one worth remembering: a Timing Advance Command, a DRX Command or a Long BSR can be forged or replayed and nothing in the AS security architecture notices.
Only the data part of a PDCP PDU is ciphered. The PDCP header, including the sequence number, is integrity protected but transmitted in clear TS 38.323 cl. 6.2.2 -- it has to be, because the receiver needs the SN to reconstruct the COUNT that the deciphering itself depends on. Any SDAP header is treated the same way. If your dissector shows you a plausible SN and then garbage payload, that is not a corrupted PDU; that is a correct PDU you do not have the key for.
There is a subtlety on SRB1 that catches people. The security configuration is applied to the SRB1 PDCP entity without a PDCP re-establishment: the entity keeps its COUNT and its window, and simply starts applying integrity protection and, later, ciphering to new PDUs TS 38.331 cl. 5.3.4.3. This is what makes the asymmetric ciphering start of §5 possible at all -- the same PDCP entity, on the same bearer, with continuous COUNT, produces one unciphered protected PDU and then ciphered ones. It is also why COUNT continuity across the activation matters, and why a UE that resets SRB1's COUNT at activation fails its very next uplink integrity check.
4. The AS Security Mode Command Procedure
The procedure is three messages long on the air and one message long in the failure case. Its brevity is deceptive: almost everything interesting is in what state each end is in when each message crosses the interface.
- The gNB receives NGAP INITIAL CONTEXT SETUP REQUEST. It contains the Security Key IE (
K_gNB, 256 bits) and the UE Security Capabilities IE -- two 16-bit bitmaps of NR algorithms plus two more for E-UTRA TS 38.413 cl. 9.3.1.86. The gNB has no other source for either value; it cannot ask the UE. - The gNB intersects the UE's supported algorithms with its own configured priority list and picks one ciphering and one integrity algorithm (§6). It then derives all four AS keys from
K_gNB. - The gNB builds
SecurityModeCommandwithsecurityAlgorithmConfigcarryingcipheringAlgorithmandintegrityProtAlgorithm, hands it to the SRB1 PDCP entity, and configures that entity to apply integrity protection with the newK_RRCint-- but not ciphering, not yet. - The UE receives it. Because the message is not ciphered, the UE can decode it before it knows whether it can trust it, which is the only way it can learn which integrity algorithm to verify it with. It derives the four AS keys and verifies the 32-bit MAC-I.
- On success the UE sends
SecurityModeComplete-- integrity protected with the newK_RRCint, and still not ciphered. It configures its receiving side to decipher from this point onward, and its transmitting side to cipher from the next message onward. - The gNB verifies the MAC-I on
SecurityModeComplete. Only now is the procedure complete at the network side, and only now does the gNB expect ciphered uplink. - The gNB proceeds with the rest of initial context setup:
UECapabilityEnquiry(companion 26 UE Capability), thenRRCReconfigurationestablishing SRB2 and the DRBs. All of it is now both integrity protected and ciphered.
| Field | ASN.1 type / range | Set by | Effect if wrong |
|---|---|---|---|
rrc-TransactionIdentifier | INTEGER (0..3) | gNB | The UE matches SecurityModeComplete to the command by this value. A collision with an outstanding transaction makes the response ambiguous and is a classic cause of a gNB timing out on a response it actually received. |
cipheringAlgorithm | ENUMERATED {nea0, nea1, nea2, nea3, spare4..spare1} | gNB | An algorithm the UE does not support gets SecurityModeFailure. A supported but unintended algorithm silently works and shows up only as a policy audit finding. |
integrityProtAlgorithm | ENUMERATED {nia0, nia1, nia2, nia3, spare4..spare1}, OPTIONAL (Need R) | gNB | Absent means 'no change', which at initial activation means the UE has nothing to verify with -- the command is rejected. Practically it is always present in a SecurityModeCommand. |
| MAC-I (PDCP, not an RRC field) | 32 bits, appended by PDCP | gNB PDCP | The one field the UE actually authenticates on. Failure to verify is the trigger for SecurityModeFailure. |
lateNonCriticalExtension | OCTET STRING, OPTIONAL | gNB | Unused in practice. A UE that fails to skip an unknown extension rather than rejecting the message is non-compliant, and it shows up as a failure only against certain vendors. |
Table 4. SecurityModeCommand in full -- it really is this small TS 38.331 cl. 6.2.2. SecurityModeComplete and SecurityModeFailure carry only the transaction identifier.
SecurityModeComplete contains no information. That is not an oversight: its entire value is the fact that it arrived with a MAC-I the gNB can verify, which proves the UE derived the same K_RRCint from the same K_gNB. It is a key-confirmation message wearing an acknowledgement's clothes, and this is why it cannot be optimised away or piggybacked.
In a split architecture the whole procedure lives in the gNB-CU. The gNB-DU never sees the keys, never performs integrity protection, and has no visibility of the security state: F1AP carries the RRC message as an already-protected PDCP PDU inside an RRCContainer TS 38.473 cl. 8.4. When triaging, this cleanly separates the possibilities -- a MAC-I problem is always a CU-side or UE-side problem, never a DU one.
5. The Ordering Rules: Where Ciphering Starts in Each Direction
This section exists because getting it wrong is the classic AS security interop failure, and because the rule is genuinely asymmetric in a way that looks like a mistake until you see why.
| Message | Integrity protected? | Ciphered? | Why |
|---|---|---|---|
SecurityModeCommand | Yes, with the new K_RRCint | No | The UE cannot decipher it: it does not yet know which ciphering algorithm to use, because the algorithm is inside the message. Chicken and egg, resolved by not ciphering. |
SecurityModeComplete | Yes, with the new K_RRCint | No | The gNB does not yet know whether the UE accepted the command. If the complete were ciphered and the failure were not, the gNB would have to attempt both interpretations of every uplink PDU. |
SecurityModeFailure | No | No | Sent with the pre-existing configuration, which at initial activation means no protection at all. The UE has by definition rejected the new keys, so it cannot use them. |
| First downlink message after the command | Yes | Yes | The gNB configured its transmitting side the moment it submitted the command. Anything after it is ciphered, whether or not the complete has arrived. |
| First uplink message after the complete | Yes | Yes | The UE configured its transmitting side the moment it submitted the complete. Anything after it is ciphered. |
Table 5. The five cases. Rows 4 and 5 are where the asymmetry bites: downlink ciphering starts one message earlier in the sequence than uplink ciphering does.
Stated as the specification states it TS 38.331 cl. 5.3.4.3 and TS 33.501 cl. 6.7.4: the UE applies integrity protection to all subsequent messages including SecurityModeComplete, and applies ciphering to all subsequent messages after SecurityModeComplete -- so SecurityModeComplete itself is the last unciphered uplink message. The gNB, symmetrically, applies ciphering to everything it sends after SecurityModeCommand -- so SecurityModeCommand is the last unciphered downlink message.
The failure this causes. A gNB implementation that starts deciphering the uplink as soon as it sends the command -- mirroring its own transmit rule -- will attempt to decipher SecurityModeComplete. Deciphering an unciphered PDU produces plausible-looking bytes, the ASN.1 decode fails or yields a garbage message type, and the gNB reports something unhelpful like RRC decode failure on SRB1 or unexpected message. Meanwhile the UE log shows a clean send with a valid MAC-I and no error whatsoever. Every UE fails identically against that gNB, and every gNB works with that UE, so the blame lands in the wrong place for days. The signature is: activation always fails, always on the third message, always with a decode rather than an integrity error.
The mirror-image failure. A UE that starts ciphering one message too early -- ciphering SecurityModeComplete itself -- produces a MAC-I verification failure at the gNB rather than a decode failure, because the gNB integrity-checks the PDU as received and the ciphered payload no longer matches the MAC-I computed over the plaintext. The distinction between these two symptoms tells you which end is wrong before you have read a single field: decode failure at the gNB means the gNB started deciphering too early; MAC-I failure at the gNB means the UE started ciphering too early.
One more ordering detail, easy to miss. The gNB must not send any other downlink RRC message between SecurityModeCommand and the arrival of SecurityModeComplete if it wants a deterministic outcome. It is allowed to -- such a message would be ciphered, correctly -- but if the UE is about to send a failure, the gNB has sent a ciphered message to a UE that never installed the ciphering key. Well-behaved implementations serialise the procedure, which is why you normally see an idle gap of exactly one round trip in the downlink at this point in a log.
6. Algorithm Identifiers, and How the gNB Chooses
There are four ciphering algorithms and four integrity algorithms defined for NR, and two of the eight are the explicit absence of protection. All of the real ones are 128-bit key, and all of them produce a keystream (for ciphering) or a 32-bit tag (for integrity) from the same five inputs described in §8.
| Identifier | 4-bit value | Algorithm | Construction | Practical notes |
|---|---|---|---|---|
| NEA0 / NIA0 | 0000 | NULL | -- | No protection. NEA0 is common for user plane where the policy says confidentiality is not needed; NIA0 is restricted to unauthenticated emergency calls (§14). |
| 128-NEA1 / 128-NIA1 | 0001 | SNOW 3G | UEA2 keystream generator; UIA2 for integrity | Inherited from UMTS and LTE. Universally supported, rarely the first choice on new deployments. |
| 128-NEA2 / 128-NIA2 | 0010 | AES-128 | AES-CTR for ciphering; AES-CMAC for integrity | The de facto default worldwide. Hardware-accelerated in essentially every modem and every gNB, so it is also usually the cheapest. |
| 128-NEA3 / 128-NIA3 | 0011 | ZUC | ZUC keystream; 128-EIA3 for integrity | Mandated in some markets. Support is mandatory in the UE from Rel-15, but gNB-side performance varies far more than for AES. |
| spare4..spare1 | 0100..0111 | -- | -- | Reserved. A gNB that signals a spare value gets SecurityModeFailure, and it is a surprisingly common symptom of an enumeration off-by-one in a configuration import. |
Table 6. The algorithm identifiers TS 33.501 cl. 5.11. The 4-bit value is what goes into the KDF as the algorithm identity when the AS keys are derived, which is why the identifier, not just the algorithm, is part of the key.
Selection is entirely a gNB decision, taken from two inputs and no negotiation whatsoever TS 33.501 cl. 6.7.4.
| Input | Where it comes from | Format | What the gNB does with it |
|---|---|---|---|
| UE security capabilities | The UE's NAS Registration Request, forwarded by the AMF in the NGAP UE Security Capabilities IE | nRencryptionAlgorithms and nRintegrityProtectionAlgorithms, each a BIT STRING (SIZE(16)) where bit 0 is NEA1/NIA1, bit 1 is NEA2/NIA2, bit 2 is NEA3/NIA3 | Treats it as the hard constraint. NEA0 and NIA0 are not represented in the bitmap because support for them is mandatory. |
| Local priority list | gNB configuration, per PLMN or per cell | An ordered list of algorithm identifiers | Walks it in order and takes the first entry that the UE also supports. |
| UP security policy (per PDU session) | The SMF, via the AMF, in the NGAP Security Indication IE | integrityProtectionIndication and confidentialityProtectionIndication, each required / preferred / not needed | Decides whether the DRB gets cipheringDisabled, and whether integrityProtection is configured (§13). Does not change which algorithm is selected. |
| Emergency indication | The NAS establishment cause / RRC cause | -- | May permit NIA0 where policy allows it (§14). |
Table 7. The selection inputs. There is no round trip: the UE stated its capabilities to the core during registration, and the gNB receives them second-hand. The companion 26 UE Capability covers why security capabilities are the one capability class that does not travel in UECapabilityInformation.
The UE's security capabilities reach the gNB from the AMF, but they were originally sent by the UE inside a NAS message that was integrity protected by the time it mattered -- and the AMF replays them back to the UE in the NAS SECURITY MODE COMMAND precisely so the UE can check they were not tampered with in the clear-text initial Registration Request TS 33.501 cl. 6.7.2. This is the bidding-down protection, and it lives in NAS, not AS. The AS layer inherits its benefit without having any mechanism of its own: there is nothing in SecurityModeCommand that lets the UE verify the gNB chose fairly, only that it chose something the UE supports.
A practical consequence for anyone reading a log: the selected pair is visible in exactly two places -- the NGAP UE Security Capabilities IE (what was possible) and securityAlgorithmConfig in the RRC (what was chosen). If a deployment is supposed to be running NIA2 and you see NIA1, the fault is in the gNB's priority list, not in the UE, and no amount of UE-side investigation will find it.
7. SecurityModeFailure, and the Failure With No Message
The UE has exactly two reasons to reject a SecurityModeCommand: the MAC-I does not verify, or the indicated algorithm is one it does not support TS 38.331 cl. 5.3.4.4. Both produce the same message, and the message carries no cause code -- which is why the surrounding context is all the diagnostic information there is.
| Cause at the UE | What it means | What you see at the gNB | Where to look |
|---|---|---|---|
| MAC-I verification failed | The UE derived a different K_RRCint from the gNB, or the message was modified in flight | SecurityModeFailure, unprotected, on SRB1 | Uplink NAS COUNT agreement between AMF and UE (§2); the Security Key IE in INITIAL CONTEXT SETUP REQUEST; whether a NAS message was retransmitted just before. |
| Indicated algorithm not supported | The gNB's priority list contains an algorithm outside the UE's capability bitmap, or a spare value | Identical SecurityModeFailure -- indistinguishable on the wire | The NGAP UE Security Capabilities bitmap against securityAlgorithmConfig. This comparison resolves it in one step, and it is the first thing to check. |
integrityProtAlgorithm absent at initial activation | Nothing to verify the message with | SecurityModeFailure | The gNB's message construction. Rare, and always a build regression rather than a configuration error. |
| No failure -- nothing sent at all | The command never arrived (RLC failure, or the UE discarded it below RRC) | Silence. No SecurityModeComplete, no SecurityModeFailure | RLC retransmission counts and any maxRetxThreshold on SRB1; whether the UE declared radio link failure (companion 16 RLM and RLF). |
Table 8. Failure triage. Note that rows 1 and 2 produce byte-identical signalling; you separate them by comparing capability bitmaps, not by decoding harder.
The recovery behaviour is clean and deserves emphasis: on failure the UE continues using the configuration it had before the command TS 38.331 cl. 5.3.4.4. It does not enter an error state, does not release the connection, and does not release SRB1. It reverts. At initial activation that means reverting to no protection at all, and SRB1 remains usable for the gNB to release the connection tidily -- or, in principle, to retry with a different algorithm pair, though almost no implementation does.
There is no 3GPP timer supervising SecurityModeCommand. T304, T310, T311 -- none of them apply here. Supervision of a missing SecurityModeComplete is entirely implementation-specific at the gNB, typically a general RRC procedure guard timer in the 100 ms to 2 s range. This matters when you are reading a log looking for a timer expiry to explain a release: there will not be a standard one, and the release cause will be something generic from the gNB's own state machine.
The gNB's options after a SecurityModeFailure are limited by specification, not by choice: without an AS security context it cannot establish SRB2, cannot set up a DRB, and cannot do anything useful with the connection. It replies to the AMF with an NGAP INITIAL CONTEXT SETUP FAILURE and releases the UE. From the subscriber's point of view the registration succeeded and no service ever appeared, which is why this failure mode generates support tickets that look like coverage problems.
8. Integrity Protection: the MAC-I and Its Five Inputs
Integrity protection in NR is a 32-bit tag computed by the sending PDCP entity, appended to the PDU, and recomputed and compared by the receiver. The integrity algorithm takes five inputs and nothing else TS 33.501 cl. 6.5 -- and because four of the five are not transmitted, an error in any of them at either end produces a failure that looks exactly like tampering.
| Input | Width | Value | Transmitted? | Consequence of a mismatch |
|---|---|---|---|---|
KEY | 128 bits | K_RRCint for an SRB, K_UPint for a DRB | No | Every PDU on that bearer fails. This is the signature of a key derivation disagreement -- all-or-nothing, from the first PDU. |
COUNT | 32 bits | HFN || PDCP SN for that bearer and direction (§10) | Only the SN part | Failures start at a specific PDU and continue. HFN desynchronisation after a loss burst is the usual cause, and it is bearer-specific. |
BEARER | 5 bits | The radio bearer identity minus one, so SRB1 gives 0x00 and DRB 1 gives 0x00 too TS 38.323 cl. 5.8 | No | Fails on every PDU of the affected bearer while another bearer with a different identity works. A strong hint at an off-by-one in the implementation. |
DIRECTION | 1 bit | 0 = uplink, 1 = downlink | No | One direction works and the other fails completely -- which is a diagnostic in itself, since a wrong key fails both. |
MESSAGE | variable | The PDCP header plus the data part, i.e. the whole PDU except the MAC-I field itself | Yes (it is the PDU) | Genuine corruption, or a disagreement about what is included -- for example whether an SDAP header counts. |
Table 9. The five inputs. The fourth column is the practical key: only MESSAGE and part of COUNT are on the air, so an integrity failure is nearly always a disagreement about something that was never transmitted.
Assembling a MAC-I for one concrete message. The UE is sending SecurityModeComplete on SRB1. NIA2 (AES-128-CMAC) was selected.
KEY = K_RRCint = KDF(K_gNB, algorithm type 0x04, algorithm identity 0x02), truncated to the 128 least significant bits of the 256-bit KDF output. Call it 2F A1 ... 9C (16 octets).
COUNT: SRB PDCP SN length is fixed at 12 bits, so COUNT = HFN(20) || SN(12). This is the fourth uplink PDU on SRB1 in this connection (RRCSetupComplete was SN 0, two NAS transports were SN 1 and 2), so SN = 3 and HFN = 0. COUNT = 0x00000003.
BEARER = SRB identity 1 minus 1 = 0x00, i.e. 00000 as five bits.
DIRECTION = 0 (uplink).
MESSAGE = the PDCP header followed by the encoded RRC message. An SRB Data PDU header is 2 octets -- four reserved bits then the 12-bit SN TS 38.323 cl. 6.2.2.1 -- so here 0x00 0x03. The RRC payload is a UL-DCCH-Message whose critical extension is securityModeComplete carrying only rrc-TransactionIdentifier = 1, which PER-encodes to 2 octets; take them as 0x2A 0x00 for this example.
So the CMAC is computed over the 4 octets 00 03 2A 00, with the 128-bit key, and with COUNT, BEARER and DIRECTION formatted into the algorithm's initial block as 128-NIA2 specifies.
Output: a 32-bit MAC-I, say 0x7B 3E 91 04, appended to give a 6-octet PDCP PDU. SecurityModeComplete is not ciphered (§5), so all 6 octets go on the air as they are.
Reading the result. The entire authentication of the AS security activation rests on those four bytes. A 32-bit tag gives an attacker a 1-in-4-billion chance per forgery attempt, and PDCP gives them no retries, because a failed check on an SRB triggers re-establishment (§17) rather than a silent discard.
What the receiver does on failure differs sharply between the two bearer types, and this is one of the most useful asymmetries in the whole architecture. On an SRB, PDCP indicates the failure to RRC and RRC initiates re-establishment TS 38.331 cl. 5.3.7.2 -- a single bad MAC-I on SRB1 costs the connection. On a DRB with integrity configured, PDCP discards the PDU and indicates the failure to upper layers TS 38.323 cl. 5.9; there is no specified RRC action, so a UE under sustained user-plane integrity failure loses throughput without losing the connection. If you are staring at a UE that keeps re-establishing, look at RRC integrity; if you are staring at one that has a connection and no throughput, look at user-plane integrity.
9. The shortMAC-I: 16 Bits That Gate Re-establishment and Resume
Re-establishment and resume both begin on SRB0, in the clear, in a cell that may not be the cell that holds the UE's context. There is no PDCP entity and therefore no MAC-I. The problem this creates is real: without some form of authentication, anyone could send an RRCReestablishmentRequest quoting a victim's C-RNTI and PCI and have the network fetch and hand over that UE's context. The shortMAC-I is the answer, and it is a 16-bit truncation of a full MAC-I computed over a very specific set of fields.
| Re-establishment | Resume | |
|---|---|---|
| Field name | shortMAC-I | resumeMAC-I |
| Width | BIT STRING (SIZE(16)) | BIT STRING (SIZE(16)) |
| Carried in | RRCReestablishmentRequest on SRB0 TS 38.331 cl. 6.2.2 | RRCResumeRequest / RRCResumeRequest1 on SRB0 |
| Computed over | VarShortMAC-Input = { sourcePhysCellId, targetCellIdentity, sourceC-RNTI } | VarResumeMAC-Input = { sourcePhysCellId, targetCellIdentity, sourceC-RNTI } |
KEY | K_RRCint of the source cell's AS security context | K_RRCint of the stored AS context from when the UE was suspended |
COUNT, BEARER, DIRECTION | All bits set to 1 -- COUNT = 0xFFFFFFFF, BEARER = 0x1F, DIRECTION = 1 | Identical |
| Result | The 16 least significant bits of the 32-bit MAC-I | Identical |
| Verified by | The gNB holding the context -- which may have to be asked for it over Xn with a RETRIEVE UE CONTEXT REQUEST | The gNB holding the context, same mechanism |
| On mismatch | RRCSetup (fallback to a fresh connection), so the UE loses its bearers and its context | RRCSetup or RRCReject; the UE falls back and NAS recovers the session |
Table 10. shortMAC-I and resumeMAC-I side by side. They are the same construction with different variable names, which is why a bug in one is almost always present in the other.
The fixed all-ones COUNT, BEARER and DIRECTION are what make this work at all -- there is no bearer and no counter to draw real values from. They also make the shortMAC-I replayable: the same inputs always produce the same 16 bits, so an attacker who observes one RRCReestablishmentRequest can replay it. The mitigation is that the inputs bind it to one source PCI, one C-RNTI and one target cell identity, so the replay only works in the same target cell for the same UE, and the context is consumed by the first successful attempt. This is a deliberate cost-benefit decision, not an oversight.
The targetCellIdentity input is the part implementations get wrong. It is the 36-bit CellIdentity of the cell the UE is re-establishing into -- not the source cell, and not the PCI. The UE reads it from the SIB1 of the new cell (companion 18 MIB and SIB1 IEs) before it can compute the value, which is why re-establishment always includes a SIB1 acquisition and why a cell broadcasting a cellIdentity that disagrees with what the CU believes it owns fails every single re-establishment into that cell while working perfectly for initial access. That is a distinctive fingerprint: 100% re-establishment failure, 0% access failure, one cell.
A shortMAC-I mismatch is not a security incident in almost every real case. The three overwhelmingly common causes are: a stale context at the source (the UE's keys were re-derived at a handover the source does not know completed), a cellIdentity provisioning mismatch as above, and a UE re-establishing after a key change on the fly using the pre-change K_RRCint. Genuine attacks look identical, which is exactly why the counter for this is worth trending rather than alarming on.
10. PDCP COUNT, Key Stream Reuse, and the Counter Check
COUNT is 32 bits, maintained per bearer per direction, and it is the freshness input that makes a static key safe to use for hours. It is also the single most fragile piece of state in the security architecture, because only its lower bits are ever transmitted.
COUNT structure. The split point moves with the configured SN length, but the total is always 32 bits -- so a longer SN buys reordering robustness at the cost of HFN headroom, not COUNT space.| Bearer type | SN length | HFN length | SNs before HFN increment | Configured by |
|---|---|---|---|---|
| SRB | 12 bits (fixed) | 20 bits | 4,096 | Not configurable TS 38.323 |
| DRB, RLC-UM or AM | 12 bits | 20 bits | 4,096 | pdcp-SN-SizeUL / pdcp-SN-SizeDL = len12bits in PDCP-Config |
| DRB, RLC-AM, high throughput | 18 bits | 14 bits | 262,144 | pdcp-SN-SizeUL / pdcp-SN-SizeDL = len18bits |
Table 11. SN and HFN sizes. The third column is the one to watch on a high-rate bearer: with an 18-bit SN the HFN has only 14 bits, and it is the HFN that runs out.
Time to COUNT exhaustion on a high-rate DRB. COUNT is 32 bits, so one key protects at most 2^32 = 4,294,967,296 PDCP PDUs per direction per bearer. That limit is in PDUs, not bytes, so small packets exhaust it far faster than large ones.\nCase A -- 1 Gbit/s of full-size PDUs. 1,500-byte PDUs: PDU rate = 1x10^9 / (1500 x 8) = 83,333 PDU/s. Time to exhaustion = 4.295x10^9 / 83,333 = 51,540 s = 14.3 hours. SN wrap, with an 18-bit SN: 262,144 / 83,333 = one HFN increment every 3.15 s.\nCase B -- 1 Gbit/s of small packets. 100-byte PDUs (gaming, signalling-heavy IoT aggregation): PDU rate = 1x10^9 / 800 = 1.25x10^6 PDU/s. Time to exhaustion = 4.295x10^9 / 1.25x10^6 = 3,436 s = 57 minutes. HFN increments every 0.21 s.\nCase C -- 4 Gbit/s of 64-byte PDUs. PDU rate = 4x10^9 / 512 = 7.81x10^6 PDU/s. Time to exhaustion = 4.295x10^9 / 7.81x10^6 = 550 s = 9.2 minutes.\nReading the result. A CA-capable UE on a loaded cell can burn through the entire COUNT space of one bearer inside a coffee break. This is why re-keying is mandatory rather than hygienic, why the gNB must monitor COUNT per bearer per direction rather than per UE, and why the intra-cell handover of §12 exists. Note also that the uplink and downlink counters exhaust at completely different times, so the trigger has to be whichever comes first.
What actually goes wrong if COUNT repeats under one key is worth spelling out, because "catastrophic" is not hyperbole. All of NEA1, NEA2 and NEA3 are stream ciphers or stream-cipher modes: they generate a keystream from (KEY, COUNT, BEARER, DIRECTION) and XOR it with the plaintext. If two different plaintexts are ever encrypted with the same four inputs, an eavesdropper who XORs the two ciphertexts gets the XOR of the two plaintexts, with the keystream cancelled out entirely. For structured traffic -- IP and TCP headers, TLS records -- that is usually enough to recover both. No key is broken and no algorithm is weakened; the confidentiality is simply gone.
The spec's requirement is absolute: the network shall not allow the same COUNT to be used more than once with the same key for the same bearer and direction, and shall re-key before it can happen TS 33.501 cl. 6.9.4.1. A UE that is about to wrap and has not been re-keyed is required to release the connection rather than reuse a COUNT. If you see an unexplained release on a very long-lived, very high-throughput bearer, check COUNT before you check the radio.
10.1 HFN desynchronisation
The HFN is never transmitted. Both ends increment it when the SN wraps, and they infer wrapping from the received SN relative to their reordering window. That inference fails if more than half the SN space is lost in one burst: the receiver sees an SN it interprets as belonging to the current HFN when the sender meant the next one. From that moment the two ends compute different COUNT values for the same PDU, so ciphering produces garbage and every integrity check fails -- permanently, on that bearer, in that direction only.
With a 12-bit SN, losing 2,048 consecutive PDUs will do it; at the 83,333 PDU/s of Case A above, that is 25 ms of total outage. This is why high-rate bearers are configured with an 18-bit SN: not for reordering depth but because 131,072 consecutive lost PDUs is a far less plausible event. The symptom is unmistakable once you know it -- one DRB, one direction, sudden and total failure, other bearers on the same UE unaffected, and no recovery until PDCP is re-established.
10.2 The counter check procedure
Because HFN divergence is silent at the RRC layer, 3GPP provides an explicit detector TS 38.331 cl. 5.3.6. The gNB sends CounterCheck listing, per DRB, the 25 most significant bits of its own uplink and downlink COUNT. The UE replies with CounterCheckResponse giving its own full 32-bit values for the same DRBs. Any discrepancy in the MSBs means the two ends have diverged.
| IE | Type / range | Direction | Purpose |
|---|---|---|---|
drb-CountMSB-InfoList | up to maxDRB (29) entries | gNB to UE | One entry per DRB the gNB wants checked. |
countMSB-Uplink, countMSB-Downlink | INTEGER (0..33554431) | gNB to UE | The 25 MSBs of COUNT -- i.e. the HFN plus the top bits of the SN. The 7 least significant bits are deliberately excluded so that PDUs in flight do not cause false positives. |
drb-CountInfoList | up to maxDRB entries | UE to gNB | The UE's reply, one entry per DRB in the request. |
count-Uplink, count-Downlink | INTEGER (0..4294967295) | UE to gNB | The UE's full 32-bit COUNT values. |
Table 12. CounterCheck and CounterCheckResponse. The asymmetry -- MSBs out, full values back -- exists so the network can see exactly how far apart the counters are, not merely that they differ.
On a mismatch the specified network action is to release the connection, or to log it for O&M TS 38.331 cl. 5.3.6.3. Nothing is repaired. That is appropriate: a mismatch means either a lost-PDU event large enough to break HFN inference, or an attacker inserting or deleting PDUs, and the safe response to both is to tear down and rebuild with fresh keys. Most deployments run counter check rarely if at all, on a long periodic timer or only on very long-lived bearers, because the procedure costs a round trip on SRB1 per UE and the failure it detects is rare.
11. Key Derivation at Handover: NH, NCC, Vertical and Horizontal
Every handover changes the AS keys. It has to: the target gNB must not be able to read what the source could, and the source must not be able to read what the target will -- the properties known as backward and forward security. The mechanism is a chain, and the UE is told which link to use by a single 3-bit field.
| Term | Definition | Range / width | Who computes it |
|---|---|---|---|
NH | Next Hop. A chain element derived from K_AMF and the previous chain element TS 33.501 Annex A.10 | 256 bits | The AMF, always. A gNB can never compute an NH. |
NCC | Next hop Chaining Count. Identifies which NH a given key was derived from | INTEGER (0..7), 3 bits | The AMF assigns it; the source gNB copies it into the RRC. |
nextHopChainingCount | The RRC field carrying the NCC to the UE, inside MasterKeyUpdate | INTEGER (0..7) | Source gNB, copied verbatim from the value received with the key. |
K_gNB* | The key the target will use as its K_gNB. Called K_NG-RAN* in XnAP/NGAP | 256 bits | The source gNB (Xn) or the AMF (NG/N2), and independently the UE. |
keySetChangeIndicator | Says the key comes from a new K_AMF rather than the chain | BOOLEAN | Source gNB, on instruction from the AMF. |
Table 13. The vocabulary. Note the fourth row: XnAP and NGAP call it K_NG-RAN* while TS 33.501 calls it K_gNB*. They are the same value, and the naming difference is a common source of confusion when correlating an Xn trace with a security specification.
Both derivations produce K_gNB* = KDF(input, target PCI, target ARFCN-DL) TS 33.501 Annex A.11. Only the input differs, and that is the entire distinction:
- Vertical derivation uses a fresh, unused
NHas the input. Because theNHwas computed by the AMF fromK_AMF, the source gNB cannot compute it and therefore cannot compute the target's key even though it forwarded it. This gives forward security -- one hop of it. - Horizontal derivation uses the source's own current
K_gNBas the input. The source obviously knows it, so it can compute the target's key. Backward security holds (the target cannot go back to the source's key) but forward security does not.
Which one happens is decided by availability, not by preference: the source uses vertical derivation if it holds an unused {NH, NCC} pair, and horizontal derivation otherwise. It signals the choice implicitly, by sending the NCC associated with whatever it used. The UE compares that NCC with the one it has stored: equal means horizontal, greater means vertical, and if it is greater by more than one the UE iterates the NH chain forward until the counts match TS 33.501 cl. 6.9.2.1.1.
NCC and NH progression across three consecutive Xn handovers. The UE has just completed AS security activation in cell A.\nInitial state. K_gNB was derived from K_AMF and the uplink NAS COUNT. It is associated with NCC = 0. The AMF has separately computed NH_1 = KDF(K_AMF, K_gNB) and associated it with NCC = 1, but it has not sent it anywhere -- INITIAL CONTEXT SETUP REQUEST carries no NH. So gNB A holds a key and no chain element.\nHandover 1, A to B (Xn). gNB A has no unused pair, so it must derive horizontally: K_gNB* = KDF(K_gNB, PCI_B, ARFCN_B). It signals nextHopChainingCount = 0. The UE sees received NCC 0 = stored NCC 0, so it performs the same horizontal derivation. gNB B's K_gNB is now K_gNB*, still associated with NCC 0. gNB B then sends PATH SWITCH REQUEST; the AMF replies with {NH_1, NCC = 1}.\nHandover 2, B to C (Xn). gNB B holds an unused {NH_1, NCC 1}, so it derives vertically: K_gNB* = KDF(NH_1, PCI_C, ARFCN_C), and signals nextHopChainingCount = 1. The UE sees 1 > 0, so it computes NH_1 itself from its own K_AMF, derives vertically, and stores NCC = 1. After the path switch the AMF gives gNB C {NH_2, NCC = 2}.\nHandover 3, C to D (Xn). Vertical again: KDF(NH_2, PCI_D, ARFCN_D), nextHopChainingCount = 2, UE sees 2 > 1 and iterates one step. Steady state reached.\nThe interesting failure. Suppose gNB C's PATH SWITCH REQUEST ACKNOWLEDGE is lost. gNB C then has no unused pair at handover 3 and must fall back to horizontal derivation with nextHopChainingCount = 1 -- the same value the UE already has. The handover succeeds perfectly. Nothing fails, no counter increments, and forward security has been silently lost for that hop. This is why NCC progression is worth trending per cell: a cell that never advances its NCC is a cell whose path switches are not completing.
| Scenario | Derivation | NCC signalled | Forward security? |
|---|---|---|---|
| Xn handover, first hop after activation | Horizontal | Unchanged | No |
| Xn handover, chain primed | Vertical | Incremented | Yes |
| NG / N2 handover | Always vertical -- the AMF is in the path and supplies a fresh NH with the request | Incremented | Yes |
| Intra-cell handover for re-keying | Either; vertical if a pair is available | Depends | Depends |
| Resume from RRC_INACTIVE | Same rule, using the NCC in RRCResume | Usually incremented | Usually |
Key change on the fly (new K_AMF) | Neither -- keySetChangeIndicator = TRUE discards the chain | Reset | Yes, trivially |
Table 14. Derivation by scenario. The third row is why NG/N2 handover has a genuine security advantage over Xn that has nothing to do with latency -- see companions 23 Xn Handover and 24 NG / N2 Handover.
The most common key-derivation bug in the field is neither vertical nor horizontal: it is a target gNB that rewrites nextHopChainingCount instead of copying the NCC it received in the HANDOVER REQUEST into the RRCReconfiguration it authors as a transparent container. The UE then derives from the wrong chain element, and every message it sends on the target's SRB1 fails its MAC-I check. The handover completes on the air -- random access succeeds, the UE transmits -- and then dies at the first integrity check, which produces a T304-less failure that looks like a radio problem in every KPI.
12. Key Change on the Fly, and Re-keying Without Moving
Two situations require new AS keys while the UE stays exactly where it is: a COUNT approaching exhaustion (§10) and a new K_AMF arriving from a re-authentication. Both are solved with the same message, and the difference between them is one boolean.
reconfigurationWithSync is what forces the PDCP re-establishment that resets COUNT to zero -- which is the actual point of the exercise in the first case.| Re-keying by intra-cell handover | Key change on the fly | |
|---|---|---|
| Trigger | COUNT approaching 2^32 on any bearer, or a scheduled key refresh policy | A new K_AMF after re-authentication or an AMF change with re-keying |
| Message | RRCReconfiguration with reconfigurationWithSync, target = the current cell | RRCReconfiguration with reconfigurationWithSync and masterKeyUpdate |
keySetChangeIndicator | FALSE | TRUE |
nextHopChainingCount | The NCC of whatever the source used | Reset -- the chain is discarded and restarted |
New K_gNB from | The NH chain or the current K_gNB (§11) | The new K_AMF and the uplink NAS COUNT |
nas-Container | Absent | Present -- carries the NAS parameters the UE needs to derive the new K_gNB consistently with the AMF |
Effect on COUNT | Reset to 0 on every bearer via PDCP re-establishment | Same |
| Effect on the UE | A full random access at the same cell, so a real interruption of a few tens of milliseconds | Same |
| Visible in a log as | A handover to the same PCI -- which looks like a bug until you know this mechanism exists | A handover to the same PCI with keySetChangeIndicator TRUE and a NAS container |
Table 15. The two re-keying paths. Row 9 is the practical takeaway: an intra-cell handover in a log is almost never a mobility error.
The reason a re-key needs reconfigurationWithSync at all -- rather than simply signalling new keys -- is COUNT. New keys with continuing counters would be pointless for the exhaustion case and dangerous for the general case, so 3GPP ties key change to PDCP re-establishment, which resets COUNT to zero on every affected bearer TS 38.331 cl. 5.3.5.6.5. That reset is only safe because the key is new: resetting COUNT under the same key would be exactly the keystream reuse of §10.
Because re-keying costs an interruption, implementations trigger it late -- and "late" has to be defined against the worst-case bearer, not the average. A vendor that triggers at 90% of the COUNT space on a bearer running Case C of §10 (9.2 minutes to exhaustion) has 55 seconds of margin. That is usually fine. A vendor that polls COUNT once a minute has none. If you see an unexplained release on a sustained multi-gigabit bearer, correlate it against elapsed bearer lifetime and PDU rate before looking at the radio.
One additional path exists for RRC_INACTIVE. When the UE resumes, RRCResume carries its own nextHopChainingCount and the UE derives a new K_gNB by exactly the rule of §11 before it sends RRCResumeComplete -- so a resume is also a re-key, and the resumeMAC-I of §9 was computed with the old key while everything after it uses the new one. The companion 14 RRC States covers the state machine; the security-relevant point is that a resume changes keys even when the UE never left the cell.
13. User-Plane Integrity Protection, and Why Rel-15 Left It Optional
Ciphering the user plane has been mandatory-to-support since the first release. Integrity-protecting it has not, and the reason is arithmetic rather than politics: a 32-bit MAC-I on every PDCP PDU is four extra octets and one extra cryptographic operation per packet, at line rate, in both directions.
| Aspect | Rel-15 | Rel-16 and later |
|---|---|---|
| UE support | Mandatory to support the algorithms, but the UE declares a maximum integrity-protected data rate, and 64 kbit/s is a permitted value | Full-rate support declared via the same IE; maxDataRate-... extensions let the UE state its real capability |
| Practical effect | A UE that says 64 kbit/s cannot have integrity on any meaningful DRB, so the network configures it on none | A UE that says full rate can have integrity on any DRB, and the SMF's policy is actually honourable |
| Where it is declared | The Integrity protection maximum data rate IE in the NAS Registration Request TS 24.501 | Same IE, with the full-rate value; the gNB learns it from the AMF |
| Per-DRB configuration | integrityProtection ENUMERATED {enabled} in PDCP-Config, already present in the Rel-15 ASN.1 | Unchanged -- the signalling was always there; only the capability to use it was missing |
| Typical deployment | Not used | Used selectively -- private networks, industrial slices, and PDU sessions whose policy says required |
Table 16. The Rel-15 to Rel-16 shift. Note that the signalling never changed: integrityProtection was in PDCP-Config from the start, and Rel-15 networks simply had no UEs able to accept it above 64 kbit/s.
The policy that decides it comes from the SMF, per PDU session, in the NGAP Security Indication IE TS 33.501 cl. 5.10.3. Each of confidentiality and integrity is required, preferred or not needed. Required means the gNB must configure it or reject the PDU session resource; preferred means configure it if the UE can; not needed means do not. A gNB that cannot honour a required integrity policy -- because the UE declared 64 kbit/s -- must fail the session resource setup, which is a genuinely useful failure: the subscriber gets no service rather than unprotected service.
| Policy value | gNB action if the UE can | gNB action if the UE cannot | PDCP effect |
|---|---|---|---|
| Integrity: required | Configure integrityProtection on the DRB | Reject the PDU session resource with an appropriate cause | MAC-I appended to every PDU; 4 octets of overhead per PDU |
| Integrity: preferred | Configure it | Proceed without it | As above, or nothing |
| Integrity: not needed | Do not configure it | Do not configure it | No MAC-I on DRB PDUs |
| Confidentiality: required | Cipher (do not set cipheringDisabled) | Reject -- but every UE can cipher, so this does not arise | Normal ciphering |
| Confidentiality: not needed | Set cipheringDisabled on the DRB | Same | No ciphering on that DRB; the PDU is on the air in clear |
Table 17. UP security policy resolution. cipheringDisabled is worth knowing about when reading a trace: an unciphered DRB in a correctly secured connection is a policy decision, not a fault.
A user-plane integrity failure behaves nothing like an RRC one. PDCP discards the PDU and tells upper layers TS 38.323 cl. 5.9; RRC is not involved and re-establishment is not triggered. So the observable is packet loss on one DRB -- retransmissions at TCP, stalls at the application, and a PDCP discard counter climbing -- with a perfectly healthy RRC connection and no security alarm anywhere. Check the PDCP integrity-failure counter per DRB; it is the only place this is visible.
14. The NULL Algorithms and the Emergency-Call Case
NEA0 and NIA0 are not "security disabled". They are formally defined algorithms that happen to be the identity function, and treating them as first-class members of the enumeration is what lets the same signalling and the same state machine cover the unprotected cases.
| NEA0 (null ciphering) | NIA0 (null integrity) | |
|---|---|---|
| What it does | Keystream is all zeros, so the ciphertext equals the plaintext | MAC-I is all zeros, and the receiver accepts any PDU |
| Legitimate uses | User plane where the SMF policy says confidentiality is not needed; lab and drive-test builds; some private deployments | Only unauthenticated emergency sessions TS 33.501 cl. 5.5 |
| On SRBs | Permitted by the ASN.1, and used in test setups. RRC signalling is then readable on the air | Effectively never, outside unauthenticated emergency |
| On DRBs | Normal and common -- signalled per DRB as cipheringDisabled rather than by selecting NEA0 for the whole UE | Not applicable; integrity is simply not configured instead |
| Diagnostic value | A trace you can read end to end. Invaluable in a lab, and the reason lab captures look nothing like field ones | None -- if you see NIA0 outside an emergency call, that is the finding |
Table 18. The two NULL algorithms. The asymmetry in the second row is the important one: NEA0 has ordinary uses and NIA0 has exactly one.
The emergency case exists because an unauthenticated UE -- one with no valid USIM, or roaming where authentication cannot complete -- must still be able to place an emergency call in jurisdictions that require it. Without authentication there is no K_AMF, therefore no K_gNB, therefore no AS keys. The only way to run the standard procedures is with NIA0 and NEA0, and 3GPP permits exactly that, for exactly that case, when local regulation requires it.
The constraint 3GPP places on NIA0 is worth quoting because it is the kind of rule that gets relaxed in a lab and then shipped: NIA0 shall be used only for unauthenticated emergency sessions, and when NAS integrity is NIA0 the AS layer shall also use NIA0 -- the two layers cannot disagree about whether this UE is authenticated TS 33.501 cl. 5.5.2. A network that offers NIA0 to authenticated UEs has disabled integrity protection for everyone who happens to be served by a gNB whose priority list starts with it, and nothing in any UE will complain.
15. Security in EN-DC and NR-DC: S-K_gNB, SRB3, keyToUse
Dual connectivity adds a second node that terminates PDCP entities, and therefore a second set of AS keys. The design keeps the master node in charge of everything: the secondary node gets a key derived by the master, cannot compute it independently, and cannot derive any further keys of its own.
| EN-DC (LTE master, NR secondary) | NR-DC (NR master, NR secondary) | |
|---|---|---|
| Master root key | K_eNB | K_gNB |
| SN root key | S-K_gNB, derived from K_eNB and sk-Counter | S-K_gNB, derived from K_gNB and sk-Counter |
| Derivation | KDF at the MN TS 33.501 cl. 6.10.2; the SN receives the result over X2-AP and can compute nothing else | Same, over XnAP |
| SN AS keys | K_RRCint, K_RRCenc, K_UPint, K_UPenc derived from S-K_gNB with the same algorithm-type distinguishers as §2 | Identical |
| Algorithm selection for the SCG | The SN chooses, within the UE's capabilities, and signals it in the SCG configuration -- it may differ from the MCG's choice | Same |
| SRB3 | Optional. Direct RRC between UE and SN, protected with the SCG keys | Optional, same |
| Refresh | Increment sk-Counter and signal it; the UE re-derives S-K_gNB and all four SCG keys | Same |
Table 19. Key handling in DC. The sk-Counter is a monotonic 16-bit counter whose only job is to make each S-K_gNB different from the last, so an SCG re-key needs no new material from the core.
The field that decides which root a given bearer uses is keyToUse in SecurityConfig inside RadioBearerConfig TS 38.331 cl. 6.3.2: master or secondary. MN-terminated bearers use master and derive from K_gNB; SN-terminated bearers use secondary and derive from S-K_gNB. This is per bearer, not per node, which is what makes split bearers and bearer type change work at all.
The failure to look for here is a bearer whose termination point moved -- an MN-terminated bearer becoming SN-terminated, or the reverse -- without keyToUse and securityAlgorithmConfig being updated in the same RRCReconfiguration. Both fields are conditionally present exactly for this case (the condition is named for bearer termination change), and omitting them leaves the UE ciphering with the wrong root key. The bearer completes its reconfiguration cleanly and then carries no useful data in either direction.
SRB3 deserves a note of its own. It is a direct RRC path between UE and SN, protected by the SCG keys, and it exists so that SCG reconfigurations do not have to traverse the master node. From a security standpoint it means there are two independent RRC integrity contexts active on one UE simultaneously, with different keys and potentially different algorithms -- so an integrity failure on SRB3 says nothing at all about the MCG's security state, and vice versa. When reading a DC log, always establish which SRB a security error was on before drawing any conclusion.
16. Parameter, IE and ASN.1 Reference
16.1 Parameter reference
| ASN.1 / IE name | Where it lives | Range or type | Typical value | Effect |
|---|---|---|---|---|
cipheringAlgorithm | SecurityAlgorithmConfig | nea0 | nea1 | nea2 | nea3 | spare | nea2 | Selects the ciphering algorithm and, via the algorithm identity input to the KDF, changes K_RRCenc and K_UPenc. |
integrityProtAlgorithm | SecurityAlgorithmConfig | nia0 | nia1 | nia2 | nia3 | spare, OPTIONAL | nia2 | Selects the integrity algorithm; changes K_RRCint and K_UPint. Absent means no change. |
keySetChangeIndicator | MasterKeyUpdate | BOOLEAN | false | TRUE: derive K_gNB from a new K_AMF and discard the NH chain. FALSE: use the chain per §11. |
nextHopChainingCount | MasterKeyUpdate | INTEGER (0..7) | increments per hop | Tells the UE which chain element to derive from. Wraps modulo 8, which is harmless because the UE only ever compares for equality or greater-than within a short window. |
nas-Container | MasterKeyUpdate | OCTET STRING, OPTIONAL | absent | Present only with keySetChangeIndicator TRUE; carries the NAS-level parameters for the new K_AMF. |
keyToUse | SecurityConfig in RadioBearerConfig | master | secondary, OPTIONAL | master | Selects K_gNB or S-K_gNB as the root for this bearer's keys (§15). |
integrityProtection | PDCP-Config (per DRB) | ENUMERATED {enabled}, OPTIONAL | absent in Rel-15 deployments | Enables UP integrity on that DRB; adds a 4-octet MAC-I to every PDU. |
cipheringDisabled | PDCP-Config (per DRB) | ENUMERATED {true}, OPTIONAL | absent | Disables ciphering on that DRB. Set when the UP confidentiality policy is not needed. |
pdcp-SN-SizeUL / pdcp-SN-SizeDL | PDCP-Config (per DRB) | len12bits | len18bits | len18bits on AM data bearers | Splits COUNT between HFN and SN (§10). Longer SN means more loss tolerance before HFN desynchronisation. |
shortMAC-I | RRCReestablishmentRequest | BIT STRING (SIZE(16)) | -- | Authenticates the re-establishment request on SRB0 (§9). |
resumeMAC-I | RRCResumeRequest / RRCResumeRequest1 | BIT STRING (SIZE(16)) | -- | The resume equivalent. |
countMSB-Uplink / countMSB-Downlink | DRB-CountMSB-Info | INTEGER (0..33554431) | -- | The 25 MSBs of COUNT for the counter check (§10.2). |
sk-Counter | Signalled with the SCG security configuration | INTEGER (0..65535) | increments per SCG re-key | Freshness input for S-K_gNB (§15). |
| Security Key (NGAP IE) | INITIAL CONTEXT SETUP REQUEST | BIT STRING (SIZE(256)) | -- | K_gNB. The gNB's only source for it. |
| UE Security Capabilities (NGAP IE) | INITIAL CONTEXT SETUP REQUEST | four BIT STRING (SIZE(16)) bitmaps | NR bitmaps with NEA1/2/3 and NIA1/2/3 set | The hard constraint on algorithm selection (§6). |
Table 20. The parameters that decide AS security behaviour. Everything here is set by the network; the UE contributes only its capabilities, and it contributes those to the core rather than to the gNB.
16.2 Abridged ASN.1
-- TS 38.331, abridged: '...' marks omitted extension markers and fields.
SecurityModeCommand ::= SEQUENCE {
rrc-TransactionIdentifier RRC-TransactionIdentifier,
criticalExtensions CHOICE {
securityModeCommand SecurityModeCommand-IEs,
criticalExtensionsFuture SEQUENCE {}
}
}
SecurityModeCommand-IEs ::= SEQUENCE {
securityConfigSMC SecurityConfigSMC,
lateNonCriticalExtension OCTET STRING OPTIONAL,
nonCriticalExtension SEQUENCE {} OPTIONAL
}
SecurityConfigSMC ::= SEQUENCE {
securityAlgorithmConfig SecurityAlgorithmConfig,
...
}
SecurityAlgorithmConfig ::= SEQUENCE {
cipheringAlgorithm CipheringAlgorithm,
integrityProtAlgorithm IntegrityProtAlgorithm OPTIONAL, -- Need R
...
}
CipheringAlgorithm ::= ENUMERATED {
nea0, nea1, nea2, nea3, spare4, spare3, spare2, spare1, ... }
IntegrityProtAlgorithm ::= ENUMERATED {
nia0, nia1, nia2, nia3, spare4, spare3, spare2, spare1, ... }
-- SecurityModeComplete and SecurityModeFailure carry no content at all
-- beyond the transaction identifier and the extension containers.
SecurityModeComplete ::= SEQUENCE {
rrc-TransactionIdentifier RRC-TransactionIdentifier,
criticalExtensions CHOICE {
securityModeComplete SecurityModeComplete-IEs,
criticalExtensionsFuture SEQUENCE {}
}
}Listing 1. The activation messages. The whole negotiation is two enumerations inside one nested SEQUENCE -- which is why so much of this document is about ordering rather than about content.
-- Key change signalling, carried inside RRCReconfiguration.
MasterKeyUpdate ::= SEQUENCE {
keySetChangeIndicator BOOLEAN,
nextHopChainingCount NextHopChainingCount,
nas-Container OCTET STRING OPTIONAL, -- Cond MasterKeyChange
...
}
NextHopChainingCount ::= INTEGER (0..7)
-- Per-bearer key selection and algorithms, in RadioBearerConfig.
SecurityConfig ::= SEQUENCE {
securityAlgorithmConfig SecurityAlgorithmConfig OPTIONAL, -- Cond RBTermChange
keyToUse ENUMERATED { master, secondary }
OPTIONAL, -- Cond RBTermChange
...
}
-- Per-DRB protection switches, in PDCP-Config.
PDCP-Config ::= SEQUENCE {
drb SEQUENCE {
discardTimer ENUMERATED { ms10, ms20, ... } OPTIONAL,
pdcp-SN-SizeUL ENUMERATED { len12bits, len18bits } OPTIONAL,
pdcp-SN-SizeDL ENUMERATED { len12bits, len18bits } OPTIONAL,
headerCompression CHOICE { notUsed NULL, rohc ..., ... },
integrityProtection ENUMERATED { enabled } OPTIONAL, -- Cond ConnectedTo5GC
statusReportRequired ENUMERATED { true } OPTIONAL,
outOfOrderDelivery ENUMERATED { true } OPTIONAL
} OPTIONAL,
moreThanOneRLC SEQUENCE { ... } OPTIONAL,
t-Reordering ENUMERATED { ms0, ms1, ... } OPTIONAL,
...,
[[ cipheringDisabled ENUMERATED { true } OPTIONAL ]] -- Cond ConnectedTo5GC1
}
-- The re-establishment authenticator, computed over VarShortMAC-Input.
RRCReestablishmentRequest-IEs ::= SEQUENCE {
ue-Identity ReestabUE-Identity,
reestablishmentCause ReestablishmentCause,
spare BIT STRING (SIZE(1))
}
ReestabUE-Identity ::= SEQUENCE {
c-RNTI RNTI-Value,
physCellId PhysCellId,
shortMAC-I ShortMAC-I
}
ShortMAC-I ::= BIT STRING (SIZE(16))
VarShortMAC-Input ::= SEQUENCE {
sourcePhysCellId PhysCellId,
targetCellIdentity CellIdentity,
sourceC-RNTI RNTI-Value
}Listing 2. Key change, per-bearer selection and the shortMAC-I construction. VarShortMAC-Input is not a transmitted message -- it is a UE variable that exists only to be the MESSAGE input to the integrity algorithm (§9).
17. Failure Modes
AS security fails in a small number of distinct ways, and almost all of them present as something other than a security problem. This table is organised around what you actually see.
| Failure | Who detects it | What the UE does | What it looks like in a log | What it points at |
|---|---|---|---|---|
| Integrity check failure on an SRB | The receiving PDCP entity; indicated to RRC | Initiates RRC re-establishment TS 38.331 cl. 5.3.7.2 | A PDCP integrity error on SRB1 or SRB2, immediately followed by RRCReestablishmentRequest on SRB0 with cause otherFailure. No radio degradation before it. | Key disagreement -- wrong K_RRCint, wrong NCC (§11), or HFN divergence on the SRB. Check the NCC in the last RRCReconfiguration first. |
| Integrity check failure on a DRB (UP integrity) | The receiving PDCP entity; indicated to upper layers only | Discards the PDU. No RRC action. | A rising PDCP discard or integrity-failure counter on one DRB, one direction. RRC is silent. Application-level stalls and TCP retransmissions. | Wrong K_UPint -- often K_RRCint used by mistake -- or a BEARER input off by one. Compare the two directions: a wrong key breaks both, a wrong DIRECTION breaks one. |
SecurityModeFailure | The UE, on the command | Reverts to the pre-command configuration and keeps SRB1 | SecurityModeFailure on SRB1, unprotected, followed by the gNB releasing the UE and sending NGAP INITIAL CONTEXT SETUP FAILURE. | Either an unsupported algorithm -- compare the NGAP capability bitmap against securityAlgorithmConfig -- or a K_gNB mismatch from uplink NAS COUNT disagreement (§2, §7). |
No SecurityModeComplete at all | The gNB, on an implementation-specific guard timer | Nothing -- it never received the command | A gap after SecurityModeCommand, then a release with a generic cause. No 3GPP timer name appears anywhere (§7). | SRB1 RLC failure, or the UE discarding the PDU below RRC. Check RLC retransmission counts and whether RLF was declared. |
shortMAC-I mismatch at re-establishment | The gNB holding the UE context | Falls back to RRCSetup, losing all bearers | RRCReestablishmentRequest answered with RRCSetup instead of RRCReestablishment. The UE then does a full NAS Service Request. | Stale context at the source, a cellIdentity provisioning mismatch in the target cell (§9), or a UE using pre-re-key keys. |
resumeMAC-I mismatch at resume | The gNB holding the suspended context | Falls back to RRCSetup or is rejected | RRCResumeRequest answered with RRCSetup/RRCReject. Repeated across many UEs in one cell if it is provisioning. | The same three causes as above; add I-RNTI ambiguity across a RAN notification area (companion 14 RRC States). |
| COUNT desynchronisation (HFN divergence) | Nobody, until a counter check runs or integrity fails | Nothing. The bearer simply stops working in one direction. | Total, sudden failure of one DRB in one direction after a large loss burst. Other bearers on the same UE are healthy. CounterCheckResponse shows differing MSBs. | A loss burst wider than half the SN space (§10.1). Consider len18bits on that bearer, and check RLC for the burst that caused it. |
| COUNT exhaustion | The gNB, if it monitors; otherwise the UE | Releases the connection rather than reuse a COUNT | An unexplained release on a very long-lived, very high-rate bearer, with nothing wrong on the radio. | A missing or too-late re-keying trigger (§10, §12). Correlate against bearer lifetime x PDU rate. |
| Key mismatch after handover | The target gNB, on the first uplink message | Nothing -- it believes it succeeded | Random access succeeds at the target, RRCReconfigurationComplete is transmitted, and then an integrity failure at the target. The UE re-establishes. T304 never expires. | A rewritten rather than copied nextHopChainingCount, or a K_gNB* computed with the wrong PCI or ARFCN-DL (§11). |
| Algorithm negotiation failure | The UE, as a SecurityModeFailure | Reverts; the connection is released | Every UE of one model, or every UE in one cell, fails identically at SecurityModeCommand. | A gNB priority list containing an algorithm outside the UE's bitmap, or a spare enumeration value from a bad configuration import (§6). |
| Ciphering start-point mismatch | The gNB, as a decode failure; or the UE, as a decode failure | Depends which end is wrong | Activation fails on the third message, every time, with a decode or ASN.1 error rather than an integrity error (§5). | One end applied ciphering one message too early or too late. Decode failure at the gNB means the gNB is wrong; MAC-I failure at the gNB means the UE is wrong. |
Wrong keyToUse after bearer termination change | Nobody -- the reconfiguration succeeds | Applies the wrong root key to that bearer | A DC bearer that reconfigures cleanly and then carries no data in either direction. Other bearers are fine. | A missing keyToUse or securityAlgorithmConfig in the reconfiguration that moved the bearer (§15). |
Table 21. The failure taxonomy. Read the fourth column first: five of these twelve produce no security-related log line at all, and three of them produce no log line anywhere.
Two of these failures are silent successes, and they are the ones worth building monitoring for: a lost path switch acknowledge that downgrades a handover to horizontal derivation (§11), and a UP confidentiality policy of not needed being applied more widely than intended (§13). Both produce healthy KPIs and reduced security. Neither will ever appear in a fault ticket.
18. Illustrative Message Traces
Illustrative trace. Field names and encodings follow 3GPP; the values are constructed for this document and are not a capture from any deployed or lab network. Key material is shown as a length only or as an obviously synthetic pattern, the PLMN is the reserved test PLMN 001-01, and IP addresses come from the RFC 5737 documentation ranges, so nothing here can be mistaken for operator data.
One UE throughout. PLMN 001-01, serving cell NR-CGI 001-01-0x0A1B2C001, PCI 231, ARFCN-DL 632628. C-RNTI 0x4C21. AMF UE NGAP ID 0x0000000012F4E2, gNB UE NGAP ID 0x00005B21. NEA2 and NIA2 selected. Timestamps are relative within one connection.
18.1 The security key arriving from the AMF
10:14:52.118 [NGAP-RX] INITIAL CONTEXT SETUP REQUEST
amf-UE-NGAP-ID .................. 0x0000000012F4E2
ran-UE-NGAP-ID .................. 0x00005B21
guami .. plmn 001-01 amf-region-id 0x02 amf-set-id 0x001 pointer 0x01
securityKey ..................... <256 bits> -- K_gNB, not logged in clear
ueSecurityCapabilities
nRencryptionAlgorithms ........ 1110 0000 0000 0000
|||
||+-- bit 2: 128-NEA3 supported
|+--- bit 1: 128-NEA2 supported
+---- bit 0: 128-NEA1 supported
nRintegrityProtectionAlgorithms 1110 0000 0000 0000 -- NIA1, NIA2, NIA3
eUTRAencryptionAlgorithms ..... 1100 0000 0000 0000 -- for EN-DC only
eUTRAintegrityProtectionAlgs .. 1100 0000 0000 0000
ue-AMBR dl = 1000000000 ul = 500000000
pduSessionResourceSetupListCxtReq
[0] pduSessionID = 5 s-NSSAI sst=0x01
securityIndication
integrityProtectionIndication ....... not-needed
confidentialityProtectionIndication . required
10:14:52.121 [SEC] algorithm selection: local priority [nea2, nea3, nea1]
UE supports {nea1, nea2, nea3} -> selected nea2
local priority [nia2, nia3, nia1]
UE supports {nia1, nia2, nia3} -> selected nia2
10:14:52.121 [SEC] derived K_RRCint (type 0x04, alg 0x02), K_RRCenc (0x03, 0x02),
K_UPint (0x06, 0x02), K_UPenc (0x05, 0x02) from K_gNBListing 3. Where selection actually happens. The bitmap in nRencryptionAlgorithms is the hard constraint; the priority list is local configuration. Note integrityProtectionIndication = not-needed, which is why no DRB in this connection will get UP integrity (§13).
18.2 SecurityModeCommand
10:14:52.124 [RRC-DL] SRB1 DCCH DL-DCCH-Message
c1 : securityModeCommand
rrc-TransactionIdentifier ..... 1
criticalExtensions : securityModeCommand
securityConfigSMC
securityAlgorithmConfig
cipheringAlgorithm ...... nea2 -- 128-NEA2, AES-128-CTR
integrityProtAlgorithm .. nia2 -- 128-NIA2, AES-128-CMAC
[PDCP-TX] SRB1 SN = 2 HFN = 0 COUNT = 0x00000002
integrityProtection = APPLIED (K_RRCint, BEARER 0x00, DIR 1)
ciphering ........... NOT APPLIED -- per TS 33.501 cl. 6.7.4
MAC-I ............... 0xA4 1C 7F 22
pdu = 00 02 | <2 octets RRC> | A4 1C 7F 22 (6 octets)
[SEC] DL ciphering state: ARMED -- next DL PDU on any SRB will be ciphered
[SEC] UL deciphering state: NOT ARMED -- expecting one unciphered UL PDUListing 4. The command. The last two lines are the state that §5 is about; a gNB that arms uplink deciphering here instead of after the complete is the trap described there.
18.3 SecurityModeComplete
10:14:52.141 [RRC-UL] SRB1 DCCH UL-DCCH-Message
[PDCP-RX] SRB1 SN = 3 HFN = 0 COUNT = 0x00000003
ciphering ........... NOT APPLIED (expected)
MAC-I received ...... 0x7B 3E 91 04
MAC-I computed ...... 0x7B 3E 91 04 -- match
integrityVerification = PASS
c1 : securityModeComplete
rrc-TransactionIdentifier ..... 1 -- matches the command
criticalExtensions : securityModeComplete { } -- no content, by design
10:14:52.141 [SEC] AS security ACTIVE. ciphering nea2, integrity nia2
10:14:52.141 [SEC] UL deciphering state: ARMED -- next UL PDU is ciphered
10:14:52.143 [RRC-DL] SRB1 ueCapabilityEnquiry
[PDCP-TX] SRB1 SN = 4 ciphering = APPLIED integrityProtection = APPLIED
-- first fully protected DL
10:14:52.168 [RRC-UL] SRB1 ueCapabilityInformation
[PDCP-RX] SRB1 SN = 5 ciphering = APPLIED integrityVerification = PASS
-- first fully protected ULListing 5. Activation completing. The four PDCP lines carry the whole of §5: unciphered command, unciphered complete, then ciphered in both directions.
18.4 SecurityModeFailure -- an unsupported algorithm
-- Same UE, different attempt. The gNB's priority list has been imported
-- with an off-by-one and now begins with a spare enumeration value.
10:22:03.401 [RRC-DL] SRB1 securityModeCommand
rrc-TransactionIdentifier ..... 0
securityAlgorithmConfig
cipheringAlgorithm ........ nea2
integrityProtAlgorithm .... spare4 -- value 4: reserved
[PDCP-TX] SRB1 SN = 2 integrityProtection = APPLIED ciphering = NOT APPLIED
10:22:03.418 [RRC-UL] SRB1 UL-DCCH-Message
[PDCP-RX] SRB1 SN = 3 ciphering = NOT APPLIED
MAC-I ............... (not verified -- no integrity context installed)
c1 : securityModeFailure
rrc-TransactionIdentifier ..... 0
criticalExtensions : securityModeFailure { } -- no cause code exists
10:22:03.418 [SEC] AS security activation FAILED. reverting to prior config
(which is: no integrity, no ciphering)
10:22:03.419 [NGAP-TX] INITIAL CONTEXT SETUP FAILURE
cause : protocol .. semantic-error
10:22:03.421 [RRC-DL] SRB1 rrcRelease
-- NOTE: the failure carries no cause. The diagnosis came entirely from
-- comparing spare4 against the UE capability bitmap in 18.1.Listing 6. A SecurityModeFailure. The message is content-free, and the releaseCause the gNB reports upstream is its own invention -- the actual cause is only visible by comparing the two algorithm sources (§7).
18.5 RRCReconfiguration carrying a key change on the fly
-- The AMF has re-authenticated the UE and pushed a new K_AMF. The gNB
-- must move to a K_gNB derived from it, without releasing the connection.
11:07:44.902 [NGAP-RX] UE CONTEXT MODIFICATION REQUEST
securityKey ..................... <256 bits> -- new K_gNB from the new K_AMF
newSecurityContextInd ........... true
11:07:44.905 [RRC-DL] SRB1 DL-DCCH-Message
c1 : rrcReconfiguration
rrc-TransactionIdentifier ..... 2
criticalExtensions : rrcReconfiguration
secondaryCellGroup ........... (absent)
masterCellGroup
spCellConfig
reconfigurationWithSync
spCellConfigCommon
physCellId ........... 231 -- SAME cell: intra-cell HO
downlinkConfigCommon .. absoluteFrequencySSB 632628
newUE-Identity ......... 0x5A03 -- new C-RNTI
t304 ................... ms100
rach-ConfigDedicated
cfra .. ssb-ResourceList [ ssb-Index 3, ra-PreambleIndex 42 ]
masterKeyUpdate
keySetChangeIndicator ...... TRUE -- new K_AMF: ignore the NH chain
nextHopChainingCount ....... 0 -- chain restarts
nas-Container .............. 0x2E 04 ... -- NAS params for the new K_AMF
[PDCP-TX] SRB1 SN = 21 ciphering = APPLIED (OLD K_RRCenc)
integrityProtection = APPLIED (OLD K_RRCint)
11:07:44.938 [PRACH-RX] preamble 42 ssb 3 -- CFRA at the same cell
11:07:44.951 [RRC-UL] SRB1 rrcReconfigurationComplete
rrc-TransactionIdentifier ..... 2
[PDCP-RX] SRB1 SN = 0 HFN = 0 -- COUNT reset by PDCP re-establishment
ciphering = APPLIED (NEW K_RRCenc) integrityVerification = PASS
11:07:44.951 [SEC] key change on the fly complete. all four AS keys re-derived
from the new K_gNB. COUNT reset to 0 on SRB1, SRB2, DRB 1Listing 7. Key change on the fly. Note the transition on one bearer: SN 21 protected with the old keys, then SN 0 with the new ones. The PDCP re-establishment that resets COUNT is what makes the reset safe (§12).
18.6 RRCReestablishmentRequest with its shortMAC-I
-- The UE lost the link at PCI 231 and has selected PCI 417, a cell
-- belonging to a different gNB reachable over Xn.
11:31:16.204 [UE-RRC] T310 expired -> radio link failure declared
11:31:16.205 [UE-RRC] initiating re-establishment (see companion 16 RLM and RLF)
11:31:16.288 [UE-RRC] cell selection complete: PCI 417, SIB1 acquired
cellIdentity = 0x0A1B3D002 -- read from the NEW cell
11:31:16.289 [UE-SEC] computing shortMAC-I
VarShortMAC-Input
sourcePhysCellId ... 231
targetCellIdentity . 0x0A1B3D002 -- target, not source
sourceC-RNTI ....... 0x5A03
KEY ................. K_RRCint of the SOURCE context
COUNT = 0xFFFFFFFF BEARER = 0x1F DIRECTION = 1
MAC-I ............... 0x91 C4 3B 7E
shortMAC-I .......... 0x3B7E -- 16 LSBs
11:31:16.294 [RRC-UL] SRB0 CCCH UL-CCCH-Message -- no PDCP, no protection
c1 : rrcReestablishmentRequest
ue-Identity
c-RNTI ..................... 0x5A03
physCellId ................. 231
shortMAC-I ................. 0x3B7E
reestablishmentCause ......... otherFailure
11:31:16.299 [XnAP-TX] RETRIEVE UE CONTEXT REQUEST -> gNB owning PCI 231
ue-ContextID .. c-RNTI 0x5A03 / physCellId 231
shortMAC-I .... 0x3B7E
11:31:16.307 [XnAP-RX] RETRIEVE UE CONTEXT RESPONSE
shortMAC-I verification = PASS
securityInformation .. key-NG-RAN-Star <256 bits> ncc = 3
11:31:16.311 [RRC-DL] SRB1 rrcReestablishment
nextHopChainingCount ......... 3 -- UE re-derives K_gNB before respondingListing 8. shortMAC-I end to end. The targetCellIdentity is the new cell's -- which is why the UE cannot compute the value until it has read SIB1 there, and why a cellIdentity provisioning error fails every re-establishment into that cell (§9).
18.7 An integrity check failure
-- Aftermath of a handover in which the target rewrote nextHopChainingCount
-- instead of copying the NCC it received in the XnAP HANDOVER REQUEST.
12:02:31.440 [XnAP-RX] HANDOVER REQUEST securityInformation.ncc = 4
12:02:31.446 [RRC-BUILD] handoverCommandMessage: masterKeyUpdate
keySetChangeIndicator = FALSE
nextHopChainingCount = 3 -- WRONG: should be 4
12:02:31.502 [PRACH-RX] preamble 17 ssb 1 -- UE arrives, RA succeeds
12:02:31.509 [RAR-TX] ta = 31 ul-grant issued c-RNTI 0x6B14
12:02:31.517 [PDCP-RX] SRB1 SN = 0 HFN = 0 COUNT = 0x00000000
deciphering ......... APPLIED (K_RRCenc from NH_3)
MAC-I received ...... 0x2C 88 F1 09
MAC-I computed ...... 0xD5 03 6A B2
integrityVerification = FAIL
12:02:31.517 [PDCP] integrity verification failure indicated to RRC, SRB1
12:02:31.517 [RRC] discarding PDU. no RRCReconfigurationComplete received.
12:02:31.518 [SEC] WARNING: SRB1 integrity failure on first UL PDU after HO
-- consistent with a K_RRCint derivation mismatch, not
-- with corruption: RLC reported no errors, CRC passed
12:02:31.598 [UE-RRC] no response to RRCReconfigurationComplete; T304 running
12:02:31.617 [UE-PDCP] SRB1 DL integrity verification FAIL (COUNT 0x00000000)
12:02:31.617 [UE-RRC] integrity check failure -> initiating re-establishment
12:02:31.702 [RRC-UL] SRB0 rrcReestablishmentRequest cause otherFailure
-- Diagnostic signature: RA succeeded, T304 did not expire, CRC and RLC
-- were clean, and the failure is on the FIRST PDU in both directions.
-- That combination means key derivation, not radio.Listing 9. An integrity check failure with its cause visible. The three facts that rule out a radio problem -- successful random access, clean CRC and RLC, and failure on the first PDU -- are the ones to look for (§17).
19. Release Deltas: Rel-15 to Rel-18
| Release | Change | Why it mattered | What it changed in a log |
|---|---|---|---|
| Rel-15 | The baseline: NEA0-3 and NIA0-3, four AS keys, SecurityModeCommand/Complete/Failure, NH/NCC chaining, integrityProtection and cipheringDisabled in PDCP-Config | Everything in this document except the items below was there from the start | -- |
| Rel-15 | UP integrity permitted but the UE may declare a maximum integrity-protected data rate of 64 kbit/s | Made UP integrity effectively unusable on real bearers (§13) | integrityProtection absent from every PDCP-Config in practice |
| Rel-16 | Full-rate UP integrity capability signalling | UP integrity becomes deployable, which is what private and industrial networks wanted | integrityProtection enabled starts appearing on DRBs, and PDCP PDUs on those DRBs grow by 4 octets |
| Rel-16 | NR-DC security formalised alongside EN-DC: S-K_gNB from K_gNB, SRB3 with SCG keys | Two independent RRC integrity contexts on one UE (§15) | keyToUse and per-SCG securityAlgorithmConfig in RadioBearerConfig |
| Rel-16 | AS security handling for the NR positioning and IIoT features that added new bearers and new SRBs | New bearers inherit the existing model rather than defining their own | Additional SRBs appearing with the same protection rules |
| Rel-17 | Small-data transmission (SDT) in RRC_INACTIVE: user data sent without a full resume, protected with the stored AS context | Protection now applies to data sent while the UE is not in RRC_CONNECTED, using keys derived at the previous suspend | Protected PDCP PDUs on a DRB with no preceding SecurityModeCommand and no RRCResume |
| Rel-17 | NR sidelink and multicast security refinements | Broadcast and sidelink cannot use a per-UE K_gNB, so they need separate handling | MBS traffic with its own key handling, outside the AS context described here |
| Rel-18 | No change to the AS SMC procedure, the algorithm set or the key hierarchy | The mechanism has been stable since Rel-15 -- unusually so | Nothing. A Rel-18 AS security trace is indistinguishable from a Rel-15 one |
| Rel-18 | 256-bit algorithm work (NEA4/NIA4 and successors) is study and specification in progress, not deployed | Anticipates post-quantum and long-term key-length concerns; the hierarchy already carries 256-bit keys, only the algorithms are 128-bit | Nothing yet. Treat any claim of 256-bit AS algorithms in a current product as marketing |
Table 22. Release deltas. The last two rows are the useful ones for expectation setting: AS security is one of the most stable parts of NR, so a security problem is almost never a release-version problem.
The one release delta that changes what you see is the Rel-16 UP integrity capability. If PDCP PDUs on a DRB are 4 octets longer than the SDU plus header arithmetic predicts, that DRB has integrityProtection enabled -- and the UE must be Rel-16 or later with full-rate support declared. This is also a quick way to confirm a policy is actually being applied rather than merely configured.
20. Reading AS Security in Logs: A Checklist
- Find the
SecurityModeCommandand check there is exactly one. One per RRC connection, always immediately after INITIAL CONTEXT SETUP REQUEST (§1). Two means the connection was released and rebuilt; zero on a connected UE with DRBs means you are looking at a context that came from a handover or a resume, so the activation happened elsewhere. - Compare
securityAlgorithmConfigagainst the NGAP capability bitmap. This one comparison resolves every algorithm negotiation failure and every "why is this network running NIA1" question (§6). The bitmap is in INITIAL CONTEXT SETUP REQUEST; the choice is in the RRC. If the choice is not in the bitmap, the gNB's priority list is wrong. - Verify the ciphering state on exactly three PDUs.
SecurityModeCommand: integrity yes, ciphering no.SecurityModeComplete: integrity yes, ciphering no. The next PDU in each direction: both. If activation fails on the third message with a decode error, the gNB armed deciphering too early; if it fails with a MAC-I error, the UE armed ciphering too early (§5). - On any integrity failure, first ask which bearer. SRB means the connection dies via re-establishment; DRB means the connection lives and the throughput dies (§8, §13). These are investigated completely differently and the counters live in different places.
- On any integrity failure, then ask which direction and whether it is the first PDU. Both directions failing means a wrong key. One direction means a
DIRECTIONor COUNT problem. Failure on the first PDU after a handover or re-key means derivation; failure part-way through a healthy bearer means COUNT (§17). - Match
nextHopChainingCountin the RRC against the NCC in the handover signalling. They must be equal -- the source copies, it does not compute. A mismatch is the single most common key-derivation bug and it presents as a post-handover integrity failure with no T304 expiry (§11). - Trend NCC progression per cell. A cell whose NCC never advances is a cell whose PATH SWITCH REQUEST ACKNOWLEDGE is not arriving, and every handover out of it is silently horizontal (§11). Nothing else will tell you this.
- On a
shortMAC-IorresumeMAC-Imismatch, check the target cell'scellIdentitybefore anything else. A cell whose broadcastcellIdentitydisagrees with what the CU believes it owns fails 100% of re-establishments into it and 0% of initial accesses (§9). That fingerprint is unmistakable and takes one SIB1 decode to confirm. - For an unexplained release on a long-lived high-rate bearer, compute the COUNT. Multiply elapsed bearer lifetime by PDU rate and compare against 2^32 (§10). If you are within an order of magnitude, the release is a re-keying trigger that fired late or a UE refusing to reuse a
COUNT. - Treat an intra-cell handover as a re-key, not a bug. A
reconfigurationWithSyncwhose target PCI equals the serving PCI is either a COUNT refresh or a key change on the fly;keySetChangeIndicatortells you which (§12). - In DC, always establish which SRB and which root key. SRB1/SRB2 use
K_gNB; SRB3 and SN-terminated DRBs useS-K_gNB. An SRB3 integrity failure says nothing about the MCG, and a bearer that reconfigured cleanly and then carried nothing is akeyToUseomission (§15). - Audit for NIA0 and for
cipheringDisabledbreadth. NIA0 outside an unauthenticated emergency session is a finding, not an observation (§14).cipheringDisabledon more DRBs than the SMF policy intended is the other silent security downgrade (§13).
21. Glossary
| Term | Expansion | Meaning in this document |
|---|---|---|
| AS security | Access Stratum security | Integrity protection and ciphering performed by PDCP between UE and gNB. The subject of this document. |
| NAS security | Non-Access Stratum security | The independent layer protecting UE-to-AMF signalling. Prerequisite for AS security, because K_gNB comes from K_AMF (§1). |
| K | -- | The permanent subscriber key, in the USIM and the UDM only. Root of everything. |
K_AUSF, K_SEAF, K_AMF | -- | The intermediate keys between K and K_gNB, held in the home network, the serving network anchor and the AMF respectively (§2). |
K_gNB | -- | The gNB's root key, derived from K_AMF and the uplink NAS COUNT. All four AS keys come from it. |
K_RRCint, K_RRCenc | -- | RRC integrity and ciphering keys. Used on SRB1, SRB2 and (with the SCG root) SRB3. |
K_UPint, K_UPenc | -- | User-plane integrity and ciphering keys. K_UPint is only used on DRBs with integrityProtection configured (§13). |
S-K_gNB | -- | The secondary node's root key in EN-DC and NR-DC, derived by the master from K_eNB or K_gNB plus sk-Counter (§15). |
| MAC-I | Message Authentication Code for Integrity | The 32-bit tag appended to a PDCP PDU and verified by the receiver (§8). Not to be confused with the MAC layer. |
shortMAC-I | -- | The 16 least significant bits of a MAC-I computed over VarShortMAC-Input, carried in RRCReestablishmentRequest on SRB0 (§9). |
resumeMAC-I | -- | The same construction for RRCResumeRequest, over VarResumeMAC-Input. |
| COUNT | -- | The 32-bit PDCP counter, HFN || SN, per bearer per direction. Freshness input to both ciphering and integrity (§10). |
| HFN | Hyper Frame Number | The upper part of COUNT. Never transmitted; inferred from SN wrapping, which is why it can desynchronise (§10.1). |
NH | Next Hop | A chain element derived by the AMF from K_AMF. Input to vertical key derivation at handover (§11). |
| NCC | Next hop Chaining Count | 0..7. Identifies which NH a key came from; signalled as nextHopChainingCount and compared by the UE against its stored value. |
| Vertical derivation | -- | K_gNB* derived from a fresh NH. Gives forward security; the source cannot compute the target's key. |
| Horizontal derivation | -- | K_gNB* derived from the source's own K_gNB. No forward security; used when no unused NH is available. |
| Key change on the fly | -- | Re-keying from a new K_AMF without releasing the connection, signalled by keySetChangeIndicator = TRUE (§12). |
| NEA0-3 / NIA0-3 | NR Encryption / Integrity Algorithm | NULL, SNOW 3G, AES-128 and ZUC respectively. The 4-bit identifier is itself an input to the key derivation (§6). |
| Counter check | -- | The RRC procedure comparing the 25 MSBs of COUNT between UE and gNB to detect divergence (§10.2). |
keyToUse | -- | Per-bearer selection of K_gNB (master) or S-K_gNB (secondary) as the key root (§15). |
22. References
- 3GPP TS 33.501 -- Security architecture and procedures for the 5G System. Clause 5.5 (NULL algorithms and the emergency case), clause 5.10 (user-plane security policy), clause 5.11 (algorithm identifiers), clause 6.2 (the key hierarchy), clause 6.4 (NAS security), clause 6.5 (AS security and the MAC-I), clause 6.7 (security mode command procedures and the ciphering start rules), clause 6.9 (key handling in state transitions and handover, including NH/NCC, vertical and horizontal derivation, and the COUNT reuse prohibition), clause 6.10 (dual connectivity and
S-K_gNB), Annex A (all key derivation functions, including A.8 for the AS keys, A.9 forK_gNB, A.10 forNHand A.11 forK_gNB*). - 3GPP TS 38.331 -- RRC protocol specification. Clause 5.3.4 (AS security mode command procedure), clause 5.3.5 (RRC reconfiguration, including
reconfigurationWithSyncand the PDCP re-establishment that resets COUNT), clause 5.3.6 (counter check), clause 5.3.7 (re-establishment and its triggers, including integrity check failure), clause 5.3.13 (resume), clause 6.2.2 (message definitions:SecurityModeCommand,SecurityModeComplete,SecurityModeFailure,RRCReestablishmentRequest,RRCResumeRequest,CounterCheck), clause 6.3.2 (SecurityConfig,SecurityAlgorithmConfig,MasterKeyUpdate,PDCP-Config), clause 6.3.3 (VarShortMAC-Input,VarResumeMAC-Input). - 3GPP TS 38.323 -- PDCP specification. Clause 5.8 (ciphering and deciphering, including the
BEARERandDIRECTIONinputs), clause 5.9 (integrity protection and verification, and the action on failure), clause 6.2.2 (Data PDU formats for SRBs and DRBs, showing where the MAC-I sits), clause 7.1 (the COUNT state variables). - 3GPP TS 38.413 -- NG Application Protocol (NGAP). Clause 8.3 (UE context management, including Initial Context Setup and UE Context Modification), clause 9.3.1 (the Security Key, UE Security Capabilities and Security Indication IEs).
- 3GPP TS 38.423 -- Xn Application Protocol (XnAP). The security information carried in HANDOVER REQUEST (
K_NG-RAN*and the NCC) and in RETRIEVE UE CONTEXT REQUEST/RESPONSE (theshortMAC-Icheck). - 3GPP TS 38.473 -- F1 Application Protocol (F1AP). Clause 8.4 (RRC message transfer) -- relevant because the gNB-DU never holds a key.
- 3GPP TS 37.340 -- Multi-connectivity; overall description. Clause 10.2 (security in EN-DC and NR-DC,
S-K_gNBand SRB3). - 3GPP TS 24.501 -- NAS protocol for 5GS. Clause 5.4.2 (NAS security mode control), clause 9.11.3 (the UE security capability and integrity protection maximum data rate IEs sent in the Registration Request).
- 3GPP TS 33.401 -- 3GPP System Architecture Evolution: security architecture. Useful for the EN-DC case, where the master root is
K_eNBand the key handling is EPS. - 3GPP TS 35.215 / 35.221 / 35.231 -- the algorithm specifications themselves: SNOW 3G (UEA2/UIA2), the 128-EEA2/EIA2 AES constructions, and ZUC (128-EEA3/EIA3).
Companion documents in this set
- 01 Registration Process -- where NAS security comes from, the authentication run that produces
K_AUSFandK_SEAF, and the key hierarchy aboveK_gNB(§1, §2). - 13 RRC Overview -- the SRBs, which of them exist before AS security activation, and why the pre-security window in §1 is safe.
- 14 RRC States -- suspend and resume, the stored AS context, and the
resumeMAC-Iof §9. - 16 RLM and RLF -- how a UE gets to re-establishment in the first place, and the
shortMAC-Iit needs when it arrives (§9). - 22 Handover Overview --
reconfigurationWithSync, T304, and the framework the key derivation of §11 sits inside. - 23 Xn Handover --
K_NG-RAN*and the NCC in HANDOVER REQUEST, the path switch that reseeds theNHchain, and why the first Xn hop is horizontal (§11). - 24 NG / N2 Handover -- the case where the AMF is in the path and supplies a fresh
NH, so derivation is always vertical (§11). - 25 Conditional Handover and DAPS -- multiple prepared targets, each needing its own
K_gNB*, and the key handling that makes DAPS's dual connection possible. - 26 UE Capability -- how UE capabilities are signalled, and why security capabilities are the exception that travels in NAS rather than in
UECapabilityInformation(§6). - 07 MAC PDU and CEs -- the MAC control elements that, as §3 notes, have no integrity protection on any release.