>
Home5G NRRRC — Radio Resource ControlAS Security Mode
🗂️ RRC — Radio Resource ControlAdvanced

AS Security Mode in 5G NR

Activating access-stratum ciphering and integrity via the Security Mode Command.

📚 3GPP-basedTS 38.331TS 33.501

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
  1. 01Why AS Security Exists, and the NAS / AS Split
  2. 02The 5G Key Hierarchy, from K to the Four AS Keys
  3. 03What Is Protected, on Which Bearer, by Which Key
  4. 04The AS Security Mode Command Procedure
  5. 05The Ordering Rules: Where Ciphering Starts in Each Direction
  6. 06Algorithm Identifiers, and How the gNB Chooses
  7. 07SecurityModeFailure, and the Failure With No Message
  8. 08Integrity Protection: the MAC-I and Its Five Inputs
  9. 09The shortMAC-I: 16 Bits That Gate Re-establishment and Resume
  10. 10PDCP COUNT, Key Stream Reuse, and the Counter Check
  11. 11Key Derivation at Handover: NH, NCC, Vertical and Horizontal
  12. 12Key Change on the Fly, and Re-keying Without Moving
  13. 13User-Plane Integrity Protection, and Why Rel-15 Left It Optional
  14. 14The NULL Algorithms and the Emergency-Call Case
  15. 15Security in EN-DC and NR-DC: S-K_gNB, SRB3, keyToUse
  16. 16Parameter, IE and ASN.1 Reference
  17. 17Failure Modes
  18. 18Illustrative Message Traces
  19. 19Release Deltas: Rel-15 to Rel-18
  20. 20Reading AS Security in Logs: A Checklist
  21. 21Glossary
  22. 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 securityAS security
ProtectsSignalling between UE and AMFRRC signalling and user-plane data between UE and gNB
Terminates atAMF, in the core networkgNB -- which in a shared or leased RAN may not be the operator's own equipment
Root keyK_AMFK_gNB, itself derived from K_AMF
KeysK_NASint, K_NASencK_RRCint, K_RRCenc, K_UPint, K_UPenc
Activated byNAS SECURITY MODE COMMAND / COMPLETE TS 24.501 cl. 5.4.2 -- companion 01 Registration ProcessRRC SecurityModeCommand / SecurityModeComplete TS 38.331 cl. 5.3.4 -- this document
Algorithms5G-EA0..3 and 5G-IA0..3, chosen by the AMFNEA0..3 and NIA0..3, chosen by the gNB -- the two layers may pick differently
LifetimeSurvives idle periods and gNB changes; re-keyed only on re-authentication or AMF changeRe-keyed at every handover, at every resume, and on demand
CounterNAS COUNT, per direction, per NAS connectionPDCP 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.

💡
Key point

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.

Figure 1. The hierarchy. The point of the depth is blast-radius containment: a 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.
KeyDerived fromFreshness inputHeld byLifetime
K----USIM and UDM onlyPermanent. Never transmitted, never derived from anything.
CK, IKK in the authentication vectorRANDUSIM / ARPF, transientlyOne authentication run. In 5G-AKA they are immediately consumed to produce K_AUSF.
K_AUSFCK || IK (5G-AKA) or the EMSK (EAP-AKA')Serving network nameUE and AUSF (home network)Survives serving-network change; the anchor for SoR and UE parameter update.
K_SEAFK_AUSFServing network nameUE and SEAF (in the AMF)One serving network. Discarded when the UE moves to another PLMN.
K_AMFK_SEAFSUPI and the ABBA parameterUE and AMFUntil re-authentication, AMF change with re-keying, or a NAS key change. Survives idle periods.
K_gNBK_AMFUplink NAS COUNTUE and the serving gNBOne gNB, one RRC connection, until the next re-key or handover.
NHK_AMF and the previous NH (or the initial K_gNB)the previous chain elementUE, AMF, and the gNB the AMF gave it toOne hop. Consumed by the handover that uses it (§11).
K_RRCintK_gNBalgorithm type 0x04 + integrity algorithm identityUE and gNB (the CU, in a split architecture)Until any re-derivation of K_gNB, or an algorithm change.
K_RRCencK_gNBalgorithm type 0x03 + ciphering algorithm identityUE and gNB-CUAs above.
K_UPintK_gNBalgorithm type 0x06 + integrity algorithm identityUE and gNB-CU (user-plane part)As above. Only used on DRBs that have integrity configured (§13).
K_UPencK_gNBalgorithm type 0x05 + ciphering algorithm identityUE 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.

📘
Spec detail

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.

Figure 2. Protection by bearer. SRB0 has no PDCP entity, so it can never be protected -- which is why RRCReestablishmentRequest needs the shortMAC-I of §9 carried inside the message instead.
BearerIntegrityCipheringKeys usedWhen protection begins
SRB0 (CCCH)NeverNever--Never. RRCSetupRequest, RRCSetup, RRCReestablishmentRequest, RRCResumeRequest and RRCReject are all sent in the clear.
SRB1 (DCCH)Mandatory once activeMandatory once active, unless NEA0K_RRCint, K_RRCencIntegrity from the SecurityModeCommand itself; ciphering per the asymmetric rule in §5.
SRB2 (DCCH, NAS transport)MandatoryMandatory unless NEA0K_RRCint, K_RRCencSRB2 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)MandatoryMandatory unless NEA0SCG K_RRCint, K_RRCenc from S-K_gNBFrom establishment. EN-DC and NR-DC only (§15).
DRB, MN-terminatedOnly if integrityProtection is configured for that DRBYes, unless cipheringDisabled is setK_UPint, K_UPenc from K_gNBFrom the moment the DRB is set up, which is always after activation.
DRB, SN-terminatedAs above, per DRBAs aboveK_UPint, K_UPenc from S-K_gNBFrom setup. keyToUse in SecurityConfig selects which root (§15).
RLC / MAC / PHYNeverNever--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.

🔍
What you see in logs

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.

Figure 3. The activation exchange. The two dividers are the whole content of §5 -- note that they are in different places relative to the two messages, and that neither coincides with the completion of the procedure.
  1. 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.
  2. 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.
  3. The gNB builds SecurityModeCommand with securityAlgorithmConfig carrying cipheringAlgorithm and integrityProtAlgorithm, hands it to the SRB1 PDCP entity, and configures that entity to apply integrity protection with the new K_RRCint -- but not ciphering, not yet.
  4. 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.
  5. On success the UE sends SecurityModeComplete -- integrity protected with the new K_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.
  6. 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.
  7. The gNB proceeds with the rest of initial context setup: UECapabilityEnquiry (companion 26 UE Capability), then RRCReconfiguration establishing SRB2 and the DRBs. All of it is now both integrity protected and ciphered.
FieldASN.1 type / rangeSet byEffect if wrong
rrc-TransactionIdentifierINTEGER (0..3)gNBThe 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.
cipheringAlgorithmENUMERATED {nea0, nea1, nea2, nea3, spare4..spare1}gNBAn algorithm the UE does not support gets SecurityModeFailure. A supported but unintended algorithm silently works and shows up only as a policy audit finding.
integrityProtAlgorithmENUMERATED {nia0, nia1, nia2, nia3, spare4..spare1}, OPTIONAL (Need R)gNBAbsent 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 PDCPgNB PDCPThe one field the UE actually authenticates on. Failure to verify is the trigger for SecurityModeFailure.
lateNonCriticalExtensionOCTET STRING, OPTIONALgNBUnused 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.

💡
Key point

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.

MessageIntegrity protected?Ciphered?Why
SecurityModeCommandYes, with the new K_RRCintNoThe 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.
SecurityModeCompleteYes, with the new K_RRCintNoThe 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.
SecurityModeFailureNoNoSent 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 commandYesYesThe 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 completeYesYesThe 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.

⚠️
Common pitfall

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.

⚠️
Common pitfall

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.

Identifier4-bit valueAlgorithmConstructionPractical notes
NEA0 / NIA00000NULL--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-NIA10001SNOW 3GUEA2 keystream generator; UIA2 for integrityInherited from UMTS and LTE. Universally supported, rarely the first choice on new deployments.
128-NEA2 / 128-NIA20010AES-128AES-CTR for ciphering; AES-CMAC for integrityThe de facto default worldwide. Hardware-accelerated in essentially every modem and every gNB, so it is also usually the cheapest.
128-NEA3 / 128-NIA30011ZUCZUC keystream; 128-EIA3 for integrityMandated in some markets. Support is mandatory in the UE from Rel-15, but gNB-side performance varies far more than for AES.
spare4..spare10100..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.

InputWhere it comes fromFormatWhat the gNB does with it
UE security capabilitiesThe UE's NAS Registration Request, forwarded by the AMF in the NGAP UE Security Capabilities IEnRencryptionAlgorithms and nRintegrityProtectionAlgorithms, each a BIT STRING (SIZE(16)) where bit 0 is NEA1/NIA1, bit 1 is NEA2/NIA2, bit 2 is NEA3/NIA3Treats it as the hard constraint. NEA0 and NIA0 are not represented in the bitmap because support for them is mandatory.
Local priority listgNB configuration, per PLMN or per cellAn ordered list of algorithm identifiersWalks 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 IEintegrityProtectionIndication and confidentialityProtectionIndication, each required / preferred / not neededDecides whether the DRB gets cipheringDisabled, and whether integrityProtection is configured (§13). Does not change which algorithm is selected.
Emergency indicationThe 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.

📘
Spec detail

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.

Figure 4. Both failure paths. The explicit failure leaves a usable SRB1 and a recoverable UE; the silent one leaves a gNB waiting on a timer that 3GPP never specified.
Cause at the UEWhat it meansWhat you see at the gNBWhere to look
MAC-I verification failedThe UE derived a different K_RRCint from the gNB, or the message was modified in flightSecurityModeFailure, unprotected, on SRB1Uplink 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 supportedThe gNB's priority list contains an algorithm outside the UE's capability bitmap, or a spare valueIdentical SecurityModeFailure -- indistinguishable on the wireThe 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 activationNothing to verify the message withSecurityModeFailureThe gNB's message construction. Rare, and always a build regression rather than a configuration error.
No failure -- nothing sent at allThe command never arrived (RLC failure, or the UE discarded it below RRC)Silence. No SecurityModeComplete, no SecurityModeFailureRLC 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.

⚠️
Common pitfall

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.

Figure 5. The MAC-I's position in a PDCP Data PDU. It is computed over the header and the data, and then the data and the MAC-I together are ciphered -- so a wrong ciphering key produces an integrity failure, not a deciphering error.
InputWidthValueTransmitted?Consequence of a mismatch
KEY128 bitsK_RRCint for an SRB, K_UPint for a DRBNoEvery PDU on that bearer fails. This is the signature of a key derivation disagreement -- all-or-nothing, from the first PDU.
COUNT32 bitsHFN || PDCP SN for that bearer and direction (§10)Only the SN partFailures start at a specific PDU and continue. HFN desynchronisation after a loss burst is the usual cause, and it is bearer-specific.
BEARER5 bitsThe radio bearer identity minus one, so SRB1 gives 0x00 and DRB 1 gives 0x00 too TS 38.323 cl. 5.8NoFails 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.
DIRECTION1 bit0 = uplink, 1 = downlinkNoOne direction works and the other fails completely -- which is a diagnostic in itself, since a wrong key fails both.
MESSAGEvariableThe PDCP header plus the data part, i.e. the whole PDU except the MAC-I field itselfYes (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.

💡
MAC-I INPUT ASSEMBLY

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-establishmentResume
Field nameshortMAC-IresumeMAC-I
WidthBIT STRING (SIZE(16))BIT STRING (SIZE(16))
Carried inRRCReestablishmentRequest on SRB0 TS 38.331 cl. 6.2.2RRCResumeRequest / RRCResumeRequest1 on SRB0
Computed overVarShortMAC-Input = { sourcePhysCellId, targetCellIdentity, sourceC-RNTI }VarResumeMAC-Input = { sourcePhysCellId, targetCellIdentity, sourceC-RNTI }
KEYK_RRCint of the source cell's AS security contextK_RRCint of the stored AS context from when the UE was suspended
COUNT, BEARER, DIRECTIONAll bits set to 1 -- COUNT = 0xFFFFFFFF, BEARER = 0x1F, DIRECTION = 1Identical
ResultThe 16 least significant bits of the 32-bit MAC-IIdentical
Verified byThe gNB holding the context -- which may have to be asked for it over Xn with a RETRIEVE UE CONTEXT REQUESTThe gNB holding the context, same mechanism
On mismatchRRCSetup (fallback to a fresh connection), so the UE loses its bearers and its contextRRCSetup 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.

📘
Spec detail

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.

🔍
What you see in logs

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.

Figure 6. 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 typeSN lengthHFN lengthSNs before HFN incrementConfigured by
SRB12 bits (fixed)20 bits4,096Not configurable TS 38.323
DRB, RLC-UM or AM12 bits20 bits4,096pdcp-SN-SizeUL / pdcp-SN-SizeDL = len12bits in PDCP-Config
DRB, RLC-AM, high throughput18 bits14 bits262,144pdcp-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.

💡
COUNT EXHAUSTION

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.

💡
Key point

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.

IEType / rangeDirectionPurpose
drb-CountMSB-InfoListup to maxDRB (29) entriesgNB to UEOne entry per DRB the gNB wants checked.
countMSB-Uplink, countMSB-DownlinkINTEGER (0..33554431)gNB to UEThe 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-CountInfoListup to maxDRB entriesUE to gNBThe UE's reply, one entry per DRB in the request.
count-Uplink, count-DownlinkINTEGER (0..4294967295)UE to gNBThe 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.

Figure 7. The derivation decision. The network side is a choice; the UE side is not -- the UE simply compares the received NCC with its stored one and does what the comparison dictates.
TermDefinitionRange / widthWho computes it
NHNext Hop. A chain element derived from K_AMF and the previous chain element TS 33.501 Annex A.10256 bitsThe AMF, always. A gNB can never compute an NH.
NCCNext hop Chaining Count. Identifies which NH a given key was derived fromINTEGER (0..7), 3 bitsThe AMF assigns it; the source gNB copies it into the RRC.
nextHopChainingCountThe RRC field carrying the NCC to the UE, inside MasterKeyUpdateINTEGER (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/NGAP256 bitsThe source gNB (Xn) or the AMF (NG/N2), and independently the UE.
keySetChangeIndicatorSays the key comes from a new K_AMF rather than the chainBOOLEANSource 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 NH as the input. Because the NH was computed by the AMF from K_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_gNB as 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.

Figure 8. The chain across three hops. The pattern -- horizontal once, then vertical forever -- is a direct consequence of the AMF handing out a new pair in every PATH SWITCH REQUEST ACKNOWLEDGE.
💡
NCC / NH PROGRESSION

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.

ScenarioDerivationNCC signalledForward security?
Xn handover, first hop after activationHorizontalUnchangedNo
Xn handover, chain primedVerticalIncrementedYes
NG / N2 handoverAlways vertical -- the AMF is in the path and supplies a fresh NH with the requestIncrementedYes
Intra-cell handover for re-keyingEither; vertical if a pair is availableDependsDepends
Resume from RRC_INACTIVESame rule, using the NCC in RRCResumeUsually incrementedUsually
Key change on the fly (new K_AMF)Neither -- keySetChangeIndicator = TRUE discards the chainResetYes, 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.

⚠️
Common pitfall

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.

Figure 9. Both re-keying paths. The 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 handoverKey change on the fly
TriggerCOUNT approaching 2^32 on any bearer, or a scheduled key refresh policyA new K_AMF after re-authentication or an AMF change with re-keying
MessageRRCReconfiguration with reconfigurationWithSync, target = the current cellRRCReconfiguration with reconfigurationWithSync and masterKeyUpdate
keySetChangeIndicatorFALSETRUE
nextHopChainingCountThe NCC of whatever the source usedReset -- the chain is discarded and restarted
New K_gNB fromThe NH chain or the current K_gNB (§11)The new K_AMF and the uplink NAS COUNT
nas-ContainerAbsentPresent -- carries the NAS parameters the UE needs to derive the new K_gNB consistently with the AMF
Effect on COUNTReset to 0 on every bearer via PDCP re-establishmentSame
Effect on the UEA full random access at the same cell, so a real interruption of a few tens of millisecondsSame
Visible in a log asA handover to the same PCI -- which looks like a bug until you know this mechanism existsA 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.

⚠️
Common pitfall

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.

AspectRel-15Rel-16 and later
UE supportMandatory to support the algorithms, but the UE declares a maximum integrity-protected data rate, and 64 kbit/s is a permitted valueFull-rate support declared via the same IE; maxDataRate-... extensions let the UE state its real capability
Practical effectA UE that says 64 kbit/s cannot have integrity on any meaningful DRB, so the network configures it on noneA UE that says full rate can have integrity on any DRB, and the SMF's policy is actually honourable
Where it is declaredThe Integrity protection maximum data rate IE in the NAS Registration Request TS 24.501Same IE, with the full-rate value; the gNB learns it from the AMF
Per-DRB configurationintegrityProtection ENUMERATED {enabled} in PDCP-Config, already present in the Rel-15 ASN.1Unchanged -- the signalling was always there; only the capability to use it was missing
Typical deploymentNot usedUsed 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 valuegNB action if the UE cangNB action if the UE cannotPDCP effect
Integrity: requiredConfigure integrityProtection on the DRBReject the PDU session resource with an appropriate causeMAC-I appended to every PDU; 4 octets of overhead per PDU
Integrity: preferredConfigure itProceed without itAs above, or nothing
Integrity: not neededDo not configure itDo not configure itNo MAC-I on DRB PDUs
Confidentiality: requiredCipher (do not set cipheringDisabled)Reject -- but every UE can cipher, so this does not ariseNormal ciphering
Confidentiality: not neededSet cipheringDisabled on the DRBSameNo 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.

🔍
What you see in logs

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 doesKeystream is all zeros, so the ciphertext equals the plaintextMAC-I is all zeros, and the receiver accepts any PDU
Legitimate usesUser plane where the SMF policy says confidentiality is not needed; lab and drive-test builds; some private deploymentsOnly unauthenticated emergency sessions TS 33.501 cl. 5.5
On SRBsPermitted by the ASN.1, and used in test setups. RRC signalling is then readable on the airEffectively never, outside unauthenticated emergency
On DRBsNormal and common -- signalled per DRB as cipheringDisabled rather than by selecting NEA0 for the whole UENot applicable; integrity is simply not configured instead
Diagnostic valueA trace you can read end to end. Invaluable in a lab, and the reason lab captures look nothing like field onesNone -- 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.

⚠️
Common pitfall

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 keyK_eNBK_gNB
SN root keyS-K_gNB, derived from K_eNB and sk-CounterS-K_gNB, derived from K_gNB and sk-Counter
DerivationKDF at the MN TS 33.501 cl. 6.10.2; the SN receives the result over X2-AP and can compute nothing elseSame, over XnAP
SN AS keysK_RRCint, K_RRCenc, K_UPint, K_UPenc derived from S-K_gNB with the same algorithm-type distinguishers as §2Identical
Algorithm selection for the SCGThe SN chooses, within the UE's capabilities, and signals it in the SCG configuration -- it may differ from the MCG's choiceSame
SRB3Optional. Direct RRC between UE and SN, protected with the SCG keysOptional, same
RefreshIncrement sk-Counter and signal it; the UE re-derives S-K_gNB and all four SCG keysSame

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.

⚠️
Common pitfall

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 nameWhere it livesRange or typeTypical valueEffect
cipheringAlgorithmSecurityAlgorithmConfignea0 | nea1 | nea2 | nea3 | sparenea2Selects the ciphering algorithm and, via the algorithm identity input to the KDF, changes K_RRCenc and K_UPenc.
integrityProtAlgorithmSecurityAlgorithmConfignia0 | nia1 | nia2 | nia3 | spare, OPTIONALnia2Selects the integrity algorithm; changes K_RRCint and K_UPint. Absent means no change.
keySetChangeIndicatorMasterKeyUpdateBOOLEANfalseTRUE: derive K_gNB from a new K_AMF and discard the NH chain. FALSE: use the chain per §11.
nextHopChainingCountMasterKeyUpdateINTEGER (0..7)increments per hopTells 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-ContainerMasterKeyUpdateOCTET STRING, OPTIONALabsentPresent only with keySetChangeIndicator TRUE; carries the NAS-level parameters for the new K_AMF.
keyToUseSecurityConfig in RadioBearerConfigmaster | secondary, OPTIONALmasterSelects K_gNB or S-K_gNB as the root for this bearer's keys (§15).
integrityProtectionPDCP-Config (per DRB)ENUMERATED {enabled}, OPTIONALabsent in Rel-15 deploymentsEnables UP integrity on that DRB; adds a 4-octet MAC-I to every PDU.
cipheringDisabledPDCP-Config (per DRB)ENUMERATED {true}, OPTIONALabsentDisables ciphering on that DRB. Set when the UP confidentiality policy is not needed.
pdcp-SN-SizeUL / pdcp-SN-SizeDLPDCP-Config (per DRB)len12bits | len18bitslen18bits on AM data bearersSplits COUNT between HFN and SN (§10). Longer SN means more loss tolerance before HFN desynchronisation.
shortMAC-IRRCReestablishmentRequestBIT STRING (SIZE(16))--Authenticates the re-establishment request on SRB0 (§9).
resumeMAC-IRRCResumeRequest / RRCResumeRequest1BIT STRING (SIZE(16))--The resume equivalent.
countMSB-Uplink / countMSB-DownlinkDRB-CountMSB-InfoINTEGER (0..33554431)--The 25 MSBs of COUNT for the counter check (§10.2).
sk-CounterSignalled with the SCG security configurationINTEGER (0..65535)increments per SCG re-keyFreshness input for S-K_gNB (§15).
Security Key (NGAP IE)INITIAL CONTEXT SETUP REQUESTBIT STRING (SIZE(256))--K_gNB. The gNB's only source for it.
UE Security Capabilities (NGAP IE)INITIAL CONTEXT SETUP REQUESTfour BIT STRING (SIZE(16)) bitmapsNR bitmaps with NEA1/2/3 and NIA1/2/3 setThe 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.

FailureWho detects itWhat the UE doesWhat it looks like in a logWhat it points at
Integrity check failure on an SRBThe receiving PDCP entity; indicated to RRCInitiates RRC re-establishment TS 38.331 cl. 5.3.7.2A 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 onlyDiscards 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.
SecurityModeFailureThe UE, on the commandReverts to the pre-command configuration and keeps SRB1SecurityModeFailure 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 allThe gNB, on an implementation-specific guard timerNothing -- it never received the commandA 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-establishmentThe gNB holding the UE contextFalls back to RRCSetup, losing all bearersRRCReestablishmentRequest 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 resumeThe gNB holding the suspended contextFalls back to RRCSetup or is rejectedRRCResumeRequest 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 failsNothing. 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 exhaustionThe gNB, if it monitors; otherwise the UEReleases the connection rather than reuse a COUNTAn 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 handoverThe target gNB, on the first uplink messageNothing -- it believes it succeededRandom 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 failureThe UE, as a SecurityModeFailureReverts; the connection is releasedEvery 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 mismatchThe gNB, as a decode failure; or the UE, as a decode failureDepends which end is wrongActivation 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 changeNobody -- the reconfiguration succeedsApplies the wrong root key to that bearerA 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.

💡
Key point

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

🔍
ABOUT THESE 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_gNB

Listing 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 PDU

Listing 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 UL

Listing 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 1

Listing 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 responding

Listing 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

ReleaseChangeWhy it matteredWhat it changed in a log
Rel-15The baseline: NEA0-3 and NIA0-3, four AS keys, SecurityModeCommand/Complete/Failure, NH/NCC chaining, integrityProtection and cipheringDisabled in PDCP-ConfigEverything in this document except the items below was there from the start--
Rel-15UP integrity permitted but the UE may declare a maximum integrity-protected data rate of 64 kbit/sMade UP integrity effectively unusable on real bearers (§13)integrityProtection absent from every PDCP-Config in practice
Rel-16Full-rate UP integrity capability signallingUP integrity becomes deployable, which is what private and industrial networks wantedintegrityProtection enabled starts appearing on DRBs, and PDCP PDUs on those DRBs grow by 4 octets
Rel-16NR-DC security formalised alongside EN-DC: S-K_gNB from K_gNB, SRB3 with SCG keysTwo independent RRC integrity contexts on one UE (§15)keyToUse and per-SCG securityAlgorithmConfig in RadioBearerConfig
Rel-16AS security handling for the NR positioning and IIoT features that added new bearers and new SRBsNew bearers inherit the existing model rather than defining their ownAdditional SRBs appearing with the same protection rules
Rel-17Small-data transmission (SDT) in RRC_INACTIVE: user data sent without a full resume, protected with the stored AS contextProtection now applies to data sent while the UE is not in RRC_CONNECTED, using keys derived at the previous suspendProtected PDCP PDUs on a DRB with no preceding SecurityModeCommand and no RRCResume
Rel-17NR sidelink and multicast security refinementsBroadcast and sidelink cannot use a per-UE K_gNB, so they need separate handlingMBS traffic with its own key handling, outside the AS context described here
Rel-18No change to the AS SMC procedure, the algorithm set or the key hierarchyThe mechanism has been stable since Rel-15 -- unusually soNothing. A Rel-18 AS security trace is indistinguishable from a Rel-15 one
Rel-18256-bit algorithm work (NEA4/NIA4 and successors) is study and specification in progress, not deployedAnticipates post-quantum and long-term key-length concerns; the hierarchy already carries 256-bit keys, only the algorithms are 128-bitNothing 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.

🔄
Release delta

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

  1. Find the SecurityModeCommand and 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.
  2. Compare securityAlgorithmConfig against 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.
  3. 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).
  4. 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.
  5. 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 DIRECTION or 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).
  6. Match nextHopChainingCount in 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).
  7. 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.
  8. On a shortMAC-I or resumeMAC-I mismatch, check the target cell's cellIdentity before anything else. A cell whose broadcast cellIdentity disagrees 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.
  9. 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.
  10. Treat an intra-cell handover as a re-key, not a bug. A reconfigurationWithSync whose target PCI equals the serving PCI is either a COUNT refresh or a key change on the fly; keySetChangeIndicator tells you which (§12).
  11. In DC, always establish which SRB and which root key. SRB1/SRB2 use K_gNB; SRB3 and SN-terminated DRBs use S-K_gNB. An SRB3 integrity failure says nothing about the MCG, and a bearer that reconfigured cleanly and then carried nothing is a keyToUse omission (§15).
  12. Audit for NIA0 and for cipheringDisabled breadth. NIA0 outside an unauthenticated emergency session is a finding, not an observation (§14). cipheringDisabled on more DRBs than the SMF policy intended is the other silent security downgrade (§13).

21. Glossary

TermExpansionMeaning in this document
AS securityAccess Stratum securityIntegrity protection and ciphering performed by PDCP between UE and gNB. The subject of this document.
NAS securityNon-Access Stratum securityThe 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-IMessage Authentication Code for IntegrityThe 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).
HFNHyper Frame NumberThe upper part of COUNT. Never transmitted; inferred from SN wrapping, which is why it can desynchronise (§10.1).
NHNext HopA chain element derived by the AMF from K_AMF. Input to vertical key derivation at handover (§11).
NCCNext hop Chaining Count0..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-3NR Encryption / Integrity AlgorithmNULL, 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 for K_gNB, A.10 for NH and A.11 for K_gNB*).
  • 3GPP TS 38.331 -- RRC protocol specification. Clause 5.3.4 (AS security mode command procedure), clause 5.3.5 (RRC reconfiguration, including reconfigurationWithSync and 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 BEARER and DIRECTION inputs), 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 (the shortMAC-I check).
  • 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_gNB and 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_eNB and 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_AUSF and K_SEAF, and the key hierarchy above K_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-I of §9.
  • 16 RLM and RLF -- how a UE gets to re-establishment in the first place, and the shortMAC-I it 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 the NH chain, 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.