Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions internal/ngap/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1300,13 +1300,15 @@ func handlePathSwitchRequestMain(ran *context.AmfRan,
}

if uESecurityCapabilities != nil {
amfUe.UESecurityCapability.SetEA1_128_5G(uESecurityCapabilities.NRencryptionAlgorithms.Value.Bytes[0] & 0x80)
amfUe.UESecurityCapability.SetEA2_128_5G(uESecurityCapabilities.NRencryptionAlgorithms.Value.Bytes[0] & 0x40)
amfUe.UESecurityCapability.SetEA3_128_5G(uESecurityCapabilities.NRencryptionAlgorithms.Value.Bytes[0] & 0x20)
amfUe.UESecurityCapability.SetIA1_128_5G(uESecurityCapabilities.NRintegrityProtectionAlgorithms.Value.Bytes[0] & 0x80)
amfUe.UESecurityCapability.SetIA2_128_5G(uESecurityCapabilities.NRintegrityProtectionAlgorithms.Value.Bytes[0] & 0x40)
amfUe.UESecurityCapability.SetIA3_128_5G(uESecurityCapabilities.NRintegrityProtectionAlgorithms.Value.Bytes[0] & 0x20)
// not support any E-UTRA algorithms
storedEA, storedIA := storedNRUESecurityCapability(amfUe)
receivedEA, receivedIA := receivedNRUESecurityCapability(uESecurityCapabilities)
if storedEA != receivedEA || storedIA != receivedIA {
// TODO: Include E-UTRA capability once AmfUe stores it; current NGAP builders only preserve NR bits.
ranUe.Log.Warnf("UESecurityCapabilities mismatch in PathSwitchRequest: "+
"stored NR(EA=0x%02x, IA=0x%02x), received NR(EA=0x%02x, IA=0x%02x); "+
"keep stored UE security capability",
storedEA, storedIA, receivedEA, receivedIA)
}
}

if rANUENGAPID != nil {
Expand Down Expand Up @@ -1410,6 +1412,29 @@ func handlePathSwitchRequestMain(ran *context.AmfRan,
}
}

func storedNRUESecurityCapability(amfUe *context.AmfUe) (nrEncryptionAlgorithm, nrIntegrityAlgorithm byte) {
nrEncryptionAlgorithm |= amfUe.UESecurityCapability.GetEA1_128_5G() << 7
nrEncryptionAlgorithm |= amfUe.UESecurityCapability.GetEA2_128_5G() << 6
nrEncryptionAlgorithm |= amfUe.UESecurityCapability.GetEA3_128_5G() << 5

nrIntegrityAlgorithm |= amfUe.UESecurityCapability.GetIA1_128_5G() << 7
nrIntegrityAlgorithm |= amfUe.UESecurityCapability.GetIA2_128_5G() << 6
nrIntegrityAlgorithm |= amfUe.UESecurityCapability.GetIA3_128_5G() << 5
return
}

func receivedNRUESecurityCapability(
uESecurityCapabilities *ngapType.UESecurityCapabilities,
) (nrEncryptionAlgorithm, nrIntegrityAlgorithm byte) {
if len(uESecurityCapabilities.NRencryptionAlgorithms.Value.Bytes) > 0 {
nrEncryptionAlgorithm = uESecurityCapabilities.NRencryptionAlgorithms.Value.Bytes[0] & 0xe0
}
if len(uESecurityCapabilities.NRintegrityProtectionAlgorithms.Value.Bytes) > 0 {
nrIntegrityAlgorithm = uESecurityCapabilities.NRintegrityProtectionAlgorithms.Value.Bytes[0] & 0xe0
}
return
}

func handleHandoverRequestAcknowledgeMain(ran *context.AmfRan,
targetUe *context.RanUe,
rANUENGAPID *ngapType.RANUENGAPID,
Expand Down
46 changes: 46 additions & 0 deletions internal/ngap/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/hex"
"fmt"
"net"
"strings"
"testing"

"github.com/google/uuid"
Expand Down Expand Up @@ -156,6 +157,51 @@ func NewAmfContext(amfCtx *amf_context.AMFContext) {
}
}

func TestHandlePathSwitchRequestKeepsStoredUESecurityCapabilityOnMismatch(t *testing.T) {
amfSelf := amf_context.GetSelf()
NewAmfContext(amfSelf)

sourceRan := NewAmfRan(nil)
sourceRan.AnType = "3GPP_ACCESS"
ranUe := &amf_context.RanUe{
Ran: sourceRan,
RanUeNgapId: 1,
AmfUeNgapId: 1,
Log: sourceRan.Log,
}
sourceRan.RanUeList.Store(ranUe.RanUeNgapId, ranUe)
amfSelf.RanUePool.Store(ranUe.AmfUeNgapId, ranUe)

amfUe := amfSelf.NewAmfUe("imsi-208930000007487")
amfUe.SecurityContextAvailable = true
amfUe.NgKsi.Ksi = 1
amfUe.Kamf = strings.Repeat("11", 32)
amfUe.NH = []byte(strings.Repeat("\x22", 32))
amfUe.UESecurityCapability = nasType.UESecurityCapability{
Iei: nasMessage.RegistrationRequestUESecurityCapabilityType,
Len: 2,
Buffer: []uint8{0x00, 0x00},
}
amfUe.UESecurityCapability.SetIA2_128_5G(1)

ranUe.AmfUe = amfUe
amfUe.RanUe["3GPP_ACCESS"] = ranUe

targetRan := NewAmfRan(nil)
targetRan.AnType = "3GPP_ACCESS"
sourceAMFUeNgapID := ngapType.AMFUENGAPID{Value: ranUe.AmfUeNgapId}
ranUeNgapID := ngapType.RANUENGAPID{Value: 2}
received := &ngapType.UESecurityCapabilities{}
received.NRencryptionAlgorithms.Value = aper.BitString{Bytes: []byte{0x00, 0x00}, BitLength: 16}
received.NRintegrityProtectionAlgorithms.Value = aper.BitString{Bytes: []byte{0x00, 0x00}, BitLength: 16}

handlePathSwitchRequestMain(targetRan, &ranUeNgapID, &sourceAMFUeNgapID, nil, received, nil, nil)

require.Equal(t, uint8(1), amfUe.UESecurityCapability.GetIA2_128_5G())
require.Equal(t, uint8(0), amfUe.UESecurityCapability.GetIA1_128_5G())
require.Equal(t, uint8(0), amfUe.UESecurityCapability.GetIA3_128_5G())
}

func BuildInitialUEMessage(ranUeNgapID int64, nasPdu []byte, fiveGSTmsi string) ngapType.NGAPPDU {
var TestPlmn ngapType.PLMNIdentity
var tmsi aper.OctetString
Expand Down
Loading