Deep Dive into 5G AKA Protocol: Mutual Authentication in 5G Networks Using free5gc & UERANSIM

Introduction

The UE and core network engage in a mutual authentication process using the 5G AKA protocol. The UE confirms the authenticity of the core network by comparing MAC and XMAC, while the core network verifies the UE by comparing RES and XRES. By using these verification methods, the negotiation process of the 5G AKA protocol is investigated through simulations in a 5G network environment with free5gc and UERANSIM.

0x01 Core Principles of the 5G AKA Protocol

Referring to TS33.501 and TS33.102, the core of the 5G AKA authentication protocol is based on the generation and transmission of the authentication vector (AV), verification of MAC, and authentication of RES. Its core principles can be summarized as follows:

0x011 Generation of AV by the Core Network:

The algorithms F1-F5 typically use the Milenage algorithm.

Compute Message Authentication Code (MAC): MAC = F1K(SQN || RAND || AMF);

Compute expected authentication response (XRES): XRES = F2K(RAND);

Network authentication token (AUTN): AUTN = (SQN⊕AK) || AMF || MAC;

AV: AV=RAND||XRES||CK||IK||AUTN;

When initiating authentication, the core network transmits the AV to the UE.

0x012 UE Authentication of the Core Network’s AV

Sequence number (SQN): (SQN⊕AK)⊕AK

Expected computation of message authentication code (XMAC): F1K(SQN || RAND || AMF);

Authentication of the core network by UE is achieved by comparing MAC and XMAC.

0x013 Core Network Authentication of UE RES

As shown in 0x01, while generating AV, the core network records XRES. While authenticating MAC, the UE returns RES to the core network for authentication.

The core network authenticates the UE by comparing RES and XRES.

0x014 How is K derived in the Authentication Model?

The 5G network elements utilize a hierarchical key derivation system, as shown in the diagram:

Each level of keys has corresponding Key Derivation Function (KDF) key export functions for derivation, such as K->Kausf and Kausf->Kseaf. Refer to Figure 6.2.2-1 in “TS 33.501 5G System Security Architecture and Process” for the 5G key distribution and key derivation solution for network nodes.

Regarding the bidirectional authentication model between UE and core network, K is likely the top-level PermanentKey in this hierarchical key model.

0x02 Overview of the free5gc+UERANSIM Simulation Environment

Using commands like arp, ifconfig, docker inspect, and bridge-related brctl, you can gather container IP and MAC address information, allowing you to organize the UERANSIM+free5gc simulation environment networking, as shown in the diagram:

The environment is deployed on an Ubuntu 20.04 VMware virtual machine, with 5GC network elements deployed in Docker containers on the VM. The 5GC simulated network elements simulate RAN data exchange via virtual bridge connections. The VMware virtual network card on the physical machine acts as the DN (Internet node) interfacing with the UPF in the container through a virtual bridge.

0x03 Analysis of the 5G_AKA Protocol Process:

Refer to 3GPP TS33.501 for descriptions of the two types of mutual authentication methods supported for UE and 5GC: 5G AKA and EAP AKA. The free5gc project uses the 5G AKA by default, and the protocol flow is illustrated in the diagram:

The following text will analyze this protocol process based on UERANSIM+free5gc simulated environment packet capture, project code, and protocol standards in a triform analysis. This is a universally effective method for learning network protocols and knowledge.

0x031 UDM: Generation and Transmission of AV

0x0311 Protocol Flow Location:

Corresponding to protocol flow diagram steps 1 and 2

0x0312 Packet Capture:

Using Wireshark on the interface (veth…) connecting to the udm container, you can capture packets and see the Nudm_UEAuthentication_Get Response message sent from udm to ausf, as shown in the picture:

This message reveals that the core network’s authentication protocol for the UE is 5G_AKA and carries the critical authentication vector (AV). How the authentication vector is derived is explained further below.

0x0313 Protocol Principle:

Standard 5G_AKA protocol, AV: AV=RAND||XRES||CK||IK||AUTN. Refer to section 0x01

0x0314 Code Implementation:

Focus on the code implementation related to the AV vector in the free5gc udm project, specifically the udm\producer\generate_auth_data.go GenerateAuthDataProcedure function. The code snippet provided below aligns with the protocol:

// Based on the SUI sent initially by the UE, decrypt to obtain the SUPI. Choose the authentication method based on the SUPI and contracted data; here, it is 5G_AKA    
supi, err := suci.ToSupi(supiOrSuci, udm_context.UDM_Self().GetUdmProfileAHNPrivateKey())
// Use the SUPI as a key index to obtain the authSubs authentication object.
authSubs, res, err := client.AuthenticationDataDocumentApi.QueryAuthSubsData(context.Background(), supi, nil)

// Extract the SQN from the authSubs authentication object
sqnStr := strictHex(authSubs.SequenceNumber, 12)
// Some sequence-preserving operations on SQN...

// Generate RAND parameter
RAND := make([]byte, 16)
_, err = cryptoRand.Read(RAND)

// Generate AMF parameter
AMF, err := hex.DecodeString("8000")

// Extract the OPC parameter from the authSubs object, description of the design isn't covered here
opcStr = authSubs.Opc.OpcValue

// Extract PermanentKey; in the 5G key system, the UE and the core network pre-share the PermanentKey, and other keys are derived from it.
kStr = authSubs.PermanentKey.PermanentKeyValue
k, err = hex.DecodeString(kStr)

// Compute the digest; the digest is key to the UE authenticating the core network.
err = milenage.F1(opc, k, RAND, sqn, AMF, macA, macS)
if err != nil {
    logger.UeauLog.Errorln("milenage F1 err ", err)
}

// Compute RES, CK, IK, AK, AKstar
// RES == XRES (expected RES) for server
err = milenage.F2345(opc, k, RAND, RES, CK, IK, AK, AKstar)
if err != nil {
    logger.UeauLog.Errorln("milenage F2345 err ", err)
}

// Compute AUTH payload
SQNxorAK := make([]byte, 6)
for i := 0; i < len(sqn); i++ {
    SQNxorAK[i] = sqn[i] ^ AK[i]
}
AUTN := append(append(SQNxorAK, AMF...), macA...)

// AV vector encapsulation and filling process

// Compute XRES*
key := append(CK, IK...)
FC := UeauCommon.FC_FOR_RES_STAR_XRES_STAR_DERIVATION
P0 := []byte(authInfoRequest.ServingNetworkName)
P1 := RAND
P2 := RES
kdfValForXresStar := UeauCommon.GetKDFValue(
key, FC, P0, UeauCommon.KDFLen(P0), P1, UeauCommon.KDFLen(P1), P2, UeauCommon.KDFLen(P2))
xresStar := kdfValForXresStar[len(kdfValForXresStar)/2:]

// Compute Kausf
FC = UeauCommon.FC_FOR_KAUSF_DERIVATION
P0 = []byte(authInfoRequest.ServingNetworkName)
P1 = SQNxorAK
kdfValForKausf := UeauCommon.GetKDFValue(key, FC, P0, UeauCommon.KDFLen(P0), P1, UeauCommon.KDFLen(P1))

// Fill rand, xresStar, autn, kausf
av.Rand = hex.EncodeToString(RAND)
av.XresStar = hex.EncodeToString(xresStar)
av.Autn = hex.EncodeToString(AUTN)
av.Kausf = hex.EncodeToString(kdfValForKausf)

0x032 AUSF: Calculation and Transmission of HXRES

0x0321 Protocol Flow Location:

Corresponding to protocol flow steps 3, 4, and 5

0x03211 Packet Capture:

Using Wireshark on the interface (veth…) connecting to the ausf container, you can capture packets and see the message sent to the amf:
Nausf_UEAuthentication_Authenticate Response

The image above illustrates: ausf stores XRES and, based on the AV received from UDM, calculates HXRES as per the protocol TS33.501 Appendix A.5. It also computes Kseaf through Kausf and sends a new AV (RAND, AUTN, HXRES) to AMF/SEAF.

0x03212 Protocol Principle:

Calculation of HXRES:

Extract RAND and XRES from the AV sent from udm to ausf, concatenate, then perform SHA-256 hash calculation.

0x03213 Code Implementation:

Focus on free5gc ausf project

\ausf\producer\ue_authentication.go

UeAuthPostRequestProcedure function, critical logic includes:

// Retrieve authInfoResult based on supi.
authInfoResult, rsp, err := client.GenerateAuthDataApi.GenerateAuthData(context.Background(), supiOrSuci, authInfoReq)

// Calculate HXRES using XRES; perform SHA256 on RAND and XRES derived from AV sent by udm to ausf.
concat := authInfoResult.AuthenticationVector.Rand + authInfoResult.AuthenticationVector.XresStar
......
hxresStarAll := sha256.Sum256(hxresStarBytes)
hxresStar := hex.EncodeToString(hxresStarAll[16:]) // last 128 bits

// Calculate Kseaf using Kausf, 0x6c constant, and serving network P0 as inputs.
Kausf := authInfoResult.AuthenticationVector.Kausf
......
Kseaf := UeauCommon.GetKDFValue(KausfDecode, UeauCommon.FC_FOR_KSEAF_DERIVATION, P0, UeauCommon.KDFLen(P0))
ausfUeContext.XresStar = authInfoResult.AuthenticationVector.XresStar
ausfUeContext.Kausf = Kausf
ausfUeContext.Kseaf = hex.EncodeToString(Kseaf)
ausfUeContext.Rand = authInfoResult.AuthenticationVector.Rand

// AV sent from ausf to amf includes RAND, AUTN, HXRES.
var av5gAka models.Av5gAka
av5gAka.Rand = authInfoResult.AuthenticationVector.Rand
av5gAka.Autn = authInfoResult.AuthenticationVector.Autn
av5gAka.HxresStar = hxresStar
responseBody.Var5gAuthData = av5gAka

0x033 SEAF: Sending Core Network Authentication Request to UE

0x0331 Protocol Flow Location:

Corresponding to protocol flow step 6

0x0332 Packet Capture:

Wireshark captures packets at the bridge interface (br-….) showing amf/seaf sending an
Authentication Request message to UE via NG-AP signaling (NAS message):

5G AKA protocol

The image indicates that seaf/amf sends AV containing RAND and AUTN payloads to the UE via NAS messages. It also includes ABBA (derived using Kamf key) and ngKSI (Kamf key identifier).

0x0333 Protocol Principle:

Padding of ABBA

ABBA is conveyed by SEAF (AMF) to UE, used by UE to derive Kamf, default is 0x000

0x0334 Code Implementation:

Key segments of the message encapsulation are in the following functions:

\amf\gmm\handler.go AuthenticationProcedure Function:

ue.ABBA = []uint8{0x00, 0x00} // Set as the protocol's default 0x0000
gmm_message.SendAuthenticationRequest(ue.RanUe[accessType])

\amf\gmm\message\send.go SendAuthenticationRequest Function:

nasMsg, err := BuildAuthenticationRequest(amfUe)

\amf\gmm\message\build.go BuildAuthenticationRequest Function:

authenticationRequest.SpareHalfOctetAndNgksi = nasConvert.SpareHalfOctetAndNgksiToNas(ue.NgKsi)
// ABBA as defined in AuthenticationProcedure []uint8{0x00, 0x00}
authenticationRequest.ABBA.SetABBAContents(ue.ABBA) 
......
rand, err := hex.DecodeString(av5gAka.Rand)
// RAND inherits the value from ausf
authenticationRequest.AuthenticationParameterRAND =
nasType.NewAuthenticationParameterRAND(nasMessage.AuthenticationRequestAuthenticationParameterRANDType)
copy(tmpArray[:], rand[0:16])
authenticationRequest.AuthenticationParameterRAND.SetRANDValue(tmpArray)
......
autn, err := hex.DecodeString(av5gAka.Autn)
// AUTN inherits the value from ausf
authenticationRequest.AuthenticationParameterAUTN = 
nasType.NewAuthenticationParameterAUTN(nasMessage.AuthenticationRequestAuthenticationParameterAUTNType)
authenticationRequest.AuthenticationParameterAUTN.SetLen(uint8(len(autn)))
copy(tmpArray[:], autn[0:16])
authenticationRequest.AuthenticationParameterAUTN.SetAUTN(tmpArray)

0x034 UE: UE Authentication of Core Network

0x0341 Protocol Flow Location:

Corresponding to protocol flow steps 7 and 8

0x0342 Packet Capture:

Due to the absence of an interface between gNB and UE at the time of writing, the UERANSIM project does not yet reveal the air interface; hence, packet capture analysis is not feasible. Below is the packet capture using Wireshark at the bridge interface (br-….) of the UE authentication response message:

5G AKA protocol

As shown above, the UE successfully authenticates the core network and returns the RES payload to AMF.

0x0343 Protocol Principle:

The UE verifies the core network primarily by validating the MAC in the AUTH payload. Using the pre-shared PermanentKey, the same RAND and SQN parameters, and the same Milenage function (f1-f5), the UE calculates the XMAC digest, which should match the MAC. Refer to section 0x02

0x0344 Code Implementation:

Key focus for the UE verification process is:

UERANSIM\src\auth.cpp NasMm::receiveAuthenticationRequest5gAka function

Main logic includes:

// Extract rand and autn payloads
auto &rand = msg.authParamRAND->value;
auto &autn = msg.authParamAUTN->value;
......
// Instantiate milenage object with the uscim card object (PermanentKey should be stored in usim object) and RAND
auto milenage = calculateMilenage(m_usim->m_sqn, rand);
.......
// Milenage object instantiation also computes AK, XMAC, res.., the calls to milenage f1-f5 should have been completed when the milenage object was instantiated.
auto &res = milenage.res;
auto &milenageAk = milenage.ak;
auto &milenageMac = milenage.mac_a;
........
// Pass AK, XMAC, and autn payload (containing MAC) to validateAutn function for validation.
auto autnCheck = validateAutn(milenageAk, milenageMac, autn);

0x035 SEAF: Validate HRES, and Send UE Authentication Request to AUSF

0x0351 Protocol Flow Location:

Corresponding to protocol flow steps 9 and 10

0x0352 Packet Capture:

Wireshark at the bridge connecting to the ausf container captures packets, showing seaf/amf sending to ausf
Nausf_UEAuthentication_Authenticate Request, as illustrated below:

As depicted, after SEAF verifies the UE’s HRES, it sends a UE authentication request to AUSF with payloads including at least UE_ID:supiOrsuci and network service name.

0x0353 Protocol Principle:

Refer to 3GPP TS33.501 Appendix A.5, and section 2.3.2 of this document

0x0354 Code Implementation :

Refer to the UE RES authentication process:

\amf\gmm\handler.go HandleAuthenticationResponse key code segment:

resStar := authenticationResponse.AuthenticationResponseParameter.GetRES()

// Calculate HRES* (TS 33.501 Annex A.5)
// Calculate HRES using the RES sent by UE with SHA256 computation
p0, err := hex.DecodeString(av5gAka.Rand)
......
p1 := resStar[:]
concat := append(p0, p1...)
hResStarBytes := sha256.Sum256(concat)
hResStar := hex.EncodeToString(hResStarBytes[16:])
// Compare the newly calculated HRES with the previously received HRES from AUSF to authenticate UE's legitimacy
if hResStar != av5gAka.HxresStar {
ue.GmmLog.Errorf("HRES* Validation Failure (received: %s, expected: %s)", hResStar, av5gAka.HxresStar)
......
// After successful authentication, send a UE authentication request to ausf including the RES sent by UE
response, problemDetails, err := consumer.SendAuth5gAkaConfirmRequest(ue, hex.EncodeToString(resStar[:]))

0x036 AUSF: Core Network’s Authentication of UE (Validation of RES), and UE Confirmation Response to SEAF

0x0361 Protocol Flow Location:

Corresponding to protocol flow steps 11 and 12

0x0362 Packet Capture:

Packet capture through Wireshark on the interface connecting to the ausf container reveals
Nausf_UEAuthentication_Authenticate Response as sent by seaf/amf to ausf, see below:

Upon successful authentication of the UE by AUSF, it returns a “201 Created” status, indicating registration of resources for the UE, with the resource URI being transmitted using a location payload.

0x0363 Protocol Principle:

Refer to the description in 3GPP TS33.501 6.1.3.2.0:

Regarding the core network UE verification process presented here, the focus is on the comparison of RES with the pre-stored XRES (described in section 2.2 of this document).

0x0364 Code Implementation:

Focus on free5gc ausf project

\ausf\producer\ue_authentication.go

Auth5gAkaComfirmRequestProcedure function, key logic includes:

ausfCurrentContext := ausf_context.GetAusfUeContext(currentSupi)
servingNetworkName := ausfCurrentContext.ServingNetworkName

// Compare the received RES* with the stored XRES*
// Compare RES sent by seaf to the XRES stored in the context to verify UE's legitimacy:
logger.Auth5gAkaComfirmLog.Infof("res*: %x\nXres*: %x\n", updateConfirmationData.ResStar, ausfCurrentContext.XresStar)
if strings.Compare(updateConfirmationData.ResStar, ausfCurrentContext.XresStar) == 0 
{   
    // 201 Created status
    ausfCurrentContext.AuthStatus = models.AuthResult_SUCCESS  
    responseBody.AuthResult = models.AuthResult_SUCCESS
    success = true
    logger.Auth5gAkaComfirmLog.Infoln("5G AKA confirmation succeeded")

0x04 Summary

Through packet capture, protocol analysis, and source code analysis using the free5GC+UERANSIM simulation environment, a comprehensive understanding of the protocol can be achieved. A profound understanding of the protocol and the domain knowledge is essential for a deeper exploration of 5G security. This article uses the 5G_AKA protocol as a case study, focusing on authentication-related details, hoping readers can draw parallels and advance together in 5G security research.

http5gsecuritygo