Skip to content

Commit 3210a26

Browse files
committed
feat: Add support for SUCI Concealing (Null-Scheme, Profile A and Profile B)
Signed-off-by: Valentin <[email protected]>
1 parent fd83fec commit 3210a26

File tree

10 files changed

+858
-51
lines changed

10 files changed

+858
-51
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
----
66
## Description
7-
PacketRusher is a tool, based upon [my5G-RANTester](https://github.com/my5G/my5G-RANTester), dedicated to the performance testing and automatic validation of 5G Core Networks using simulated UE (user equipment) and gNodeB (5G base station).
7+
#### Now with SUCI Concealing/Deconcealment (Null-Scheme, Profile A (X25519), Profile B (P-256))!
88

9-
If you have questions or comments, feel free to open an issue.
9+
PacketRusher is a tool dedicated to the performance testing and automatic validation of 5G Core Networks using simulated UE (user equipment) and gNodeB (5G base station).
10+
11+
If you have questions or comments, feel free to open an issue after **a careful** review of existing closed issues.
1012

1113
PacketRusher borrows libraries and data structures from the [free5gc project](https://github.com/free5gc/free5gc).
1214

@@ -16,6 +18,7 @@ PacketRusher borrows libraries and data structures from the [free5gc project](ht
1618
* Supports both N2 (NGAP) and N1 (NAS) interfaces for stress testing
1719
* --pcap parameter to capture pcap of N1/N2 traffic
1820
* Implements main control plane procedures:
21+
* SUCI Concealing/Deconcealment (Null-Scheme, Profile A (X25519), Profile B (P-256))
1922
* UE attach/detach (registration/identity request/authentification/security mode) procedures
2023
* Create/Delete PDU Sessions, up to 15 PDU Sessions per UE
2124
* Xn handover: UE handover between simulated gNodeB (PathSwitchRequest)
@@ -110,7 +113,7 @@ If you use this software, you may cite it as below:
110113
## License
111114
© Copyright 2023 Hewlett Packard Enterprise Development LP
112115

113-
© Copyright 2024 Valentin D'Emmanuele
116+
© Copyright 2024-2025 Valentin D'Emmanuele
114117

115118
This project is under the [Apache 2.0 License](LICENSE) license.
116119

config/config.go

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@
55
package config
66

77
import (
8+
"crypto/ecdh"
9+
"encoding/hex"
10+
"my5G-RANTester/internal/common/sidf"
811
"net"
912
"os"
1013
"path"
1114
"path/filepath"
15+
"strconv"
1216

1317
"github.com/free5gc/nas/nasMessage"
1418
"github.com/free5gc/nas/nasType"
19+
"github.com/goccy/go-yaml"
1520
log "github.com/sirupsen/logrus"
16-
"gopkg.in/yaml.v2"
1721
)
1822

1923
// TunnelMode indicates how to create a GTP-U tunnel interface in an UE.
@@ -33,7 +37,7 @@ var config *Config
3337
type Config struct {
3438
GNodeB GNodeB `yaml:"gnodeb"`
3539
Ue Ue `yaml:"ue"`
36-
AMFs []*AMF `yaml:"amfif"`
40+
AMFs []*AMF `yaml:"amfif"`
3741
Logs Logs `yaml:"logs"`
3842
}
3943

@@ -64,18 +68,21 @@ type SliceSupportList struct {
6468
}
6569

6670
type Ue struct {
67-
Msin string `yaml:"msin"`
68-
Key string `yaml:"key"`
69-
Opc string `yaml:"opc"`
70-
Amf string `yaml:"amf"`
71-
Sqn string `yaml:"sqn"`
72-
Dnn string `yaml:"dnn"`
73-
RoutingIndicator string `yaml:"routingindicator"`
74-
Hplmn Hplmn `yaml:"hplmn"`
75-
Snssai Snssai `yaml:"snssai"`
76-
Integrity Integrity `yaml:"integrity"`
77-
Ciphering Ciphering `yaml:"ciphering"`
78-
TunnelMode TunnelMode `yaml:"-"`
71+
Msin string `yaml:"msin"`
72+
Key string `yaml:"key"`
73+
Opc string `yaml:"opc"`
74+
Amf string `yaml:"amf"`
75+
Sqn string `yaml:"sqn"`
76+
Dnn string `yaml:"dnn"`
77+
ProtectionScheme int `yaml:"protectionScheme"`
78+
HomeNetworkPublicKey string `yaml:"homeNetworkPublicKey"`
79+
HomeNetworkPublicKeyID uint8 `yaml:"homeNetworkPublicKeyID"`
80+
RoutingIndicator string `yaml:"routingindicator"`
81+
Hplmn Hplmn `yaml:"hplmn"`
82+
Snssai Snssai `yaml:"snssai"`
83+
Integrity Integrity `yaml:"integrity"`
84+
Ciphering Ciphering `yaml:"ciphering"`
85+
TunnelMode TunnelMode `yaml:"-"`
7986
}
8087

8188
type Hplmn struct {
@@ -136,7 +143,7 @@ func readConfig(configPath string) Config {
136143
}
137144
defer f.Close()
138145

139-
decoder := yaml.NewDecoder(f)
146+
decoder := yaml.NewDecoder(f, yaml.Strict())
140147
err = decoder.Decode(&cfg)
141148
if err != nil {
142149
log.Fatal("Could not unmarshal yaml config at \"", configPath, "\". ", err.Error())
@@ -217,6 +224,54 @@ func (config *Config) GetUESecurityCapability() *nasType.UESecurityCapability {
217224
return UESecurityCapability
218225
}
219226

227+
func (config *Config) GetHomeNetworkPublicKey() sidf.HomeNetworkPublicKey {
228+
switch config.Ue.ProtectionScheme {
229+
case 0:
230+
config.Ue.HomeNetworkPublicKey = ""
231+
config.Ue.HomeNetworkPublicKeyID = 0
232+
case 1:
233+
key, err := hex.DecodeString(config.Ue.HomeNetworkPublicKey)
234+
if err != nil {
235+
log.Fatalf("Invalid Home Network Public Key in configuration for Profile A: %v", err)
236+
}
237+
238+
publicKey, err := ecdh.X25519().NewPublicKey(key)
239+
if err != nil {
240+
log.Fatalf("Invalid Home Network Public Key in configuration for Profile A: %v", err)
241+
}
242+
243+
return sidf.HomeNetworkPublicKey{
244+
ProtectionScheme: strconv.Itoa(config.Ue.ProtectionScheme),
245+
PublicKey: publicKey,
246+
PublicKeyID: strconv.Itoa(int(config.Ue.HomeNetworkPublicKeyID)),
247+
}
248+
case 2:
249+
key, err := hex.DecodeString(config.Ue.HomeNetworkPublicKey)
250+
if err != nil {
251+
log.Fatalf("Invalid Home Network Public Key in configuration for Profile B: %v", err)
252+
}
253+
254+
publicKey, err := ecdh.P256().NewPublicKey(key)
255+
if err != nil {
256+
log.Fatalf("Invalid Home Network Public Key in configuration for Profile B: %v", err)
257+
}
258+
259+
return sidf.HomeNetworkPublicKey{
260+
ProtectionScheme: strconv.Itoa(config.Ue.ProtectionScheme),
261+
PublicKey: publicKey,
262+
PublicKeyID: strconv.Itoa(int(config.Ue.HomeNetworkPublicKeyID)),
263+
}
264+
default:
265+
log.Fatal("Invalid Protection Scheme for SUCI. Valid values are 0, 1 and 2")
266+
}
267+
268+
return sidf.HomeNetworkPublicKey{
269+
ProtectionScheme: "0",
270+
PublicKey: nil,
271+
PublicKeyID: "0",
272+
}
273+
}
274+
220275
func boolToUint8(boolean bool) uint8 {
221276
if boolean {
222277
return 1

config/config.yml

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,87 @@
1+
# PacketRusher Simulated gNodeB Configuration
12
gnodeb:
3+
# IP Address on the N2 Interface (e.g. used between the gNodeB and the AMF)
24
controlif:
3-
ip: "192.168.11.13"
5+
ip: "127.0.0.1"
46
port: 9487
7+
8+
# IP Address on the N3 Interface (e.g. used between the gNodeB and the UPF)
59
dataif:
6-
ip: "192.168.11.13"
10+
ip: "127.0.0.1"
711
port: 2152
12+
13+
# gNodeB's Identity
814
plmnlist:
9-
mcc: "999"
10-
mnc: "70"
15+
mcc: "208"
16+
mnc: "93"
1117
tac: "000001"
1218
gnbid: "000008"
19+
20+
# gNodeB's Supported Slices
1321
slicesupportlist:
1422
sst: "01"
1523
sd: "000001" # optional, can be removed if not used
24+
25+
# PacketRusher Simulated UE Configuration
1626
ue:
27+
# UE's Identity, frequently called IMSI in 4G and before
28+
# IMSI format is "<mcc><mnc><msin>"
29+
# In 5G, the SUPI of the UE will be "imsi-<mcc><mnc><msin>""
30+
# With default configuration, SUPI will be imsi-208930000000120
31+
hplmn:
32+
mcc: "208"
33+
mnc: "93"
1734
msin: "0000000120"
35+
36+
# In 5G, the UE's identity to the AMF as a SUCI (Subscription Concealed Identifier)
37+
#
38+
# SUCI format is suci-<supi_type>-<MCC>-<MNC>-<routing_indicator>-<protection_scheme>-<public_key_id>-<scheme_output>
39+
# With default configuration, SUCI sent to AMF will be suci-0-999-70-0000-0-0-0000000120
40+
#
41+
# SUCI Routing Indicator allows the AMF to route the UE to the correct UDM
42+
routingindicator: "0000"
43+
#
44+
# SUCI Protection Scheme: 0 for Null-scheme, 1 for Profile A and 2 for Profile B
45+
protectionScheme: 0
46+
#
47+
# Home Network Public Key
48+
# Ignored with default Null-Scheme configuration
49+
homeNetworkPublicKey: "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"
50+
#
51+
# Home Network Public Key ID
52+
# Ignored ith default Null-Scheme configuration
53+
homeNetworkPublicKeyID: 1
54+
55+
# UE's SIM credentials
1856
key: "00112233445566778899AABBCCDDEEFF"
1957
opc: "00112233445566778899AABBCCDDEEFF"
2058
amf: "8000"
2159
sqn: "00000000"
60+
61+
# UE will request to establish a data session in this DNN (APN)
2262
dnn: "internet"
23-
routingindicator: "0000"
24-
hplmn:
25-
mcc: "999"
26-
mnc: "70"
63+
# in the following slice
2764
snssai:
28-
sst: 01
65+
sst: "01"
2966
sd: "000001" # optional, can be removed if not used
67+
68+
# The UE's security capabilities that will be advertised to the AMF
3069
integrity:
3170
nia0: false
3271
nia1: false
3372
nia2: true
3473
nia3: false
3574
ciphering:
75+
# For debugging Wireshark traces, NEA0 is recommended, as the NAS messages
76+
# will be sent in cleartext, and be decipherable in Wireshark.
3677
nea0: true
3778
nea1: false
3879
nea2: true
3980
nea3: false
81+
82+
# List of AMF that PacketRusher will try to connect to
4083
amfif:
41-
- ip: "192.168.11.30"
84+
- ip: "127.0.0.1"
4285
port: 38412
4386
logs:
4487
level: 4

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ require (
3232
github.com/aead/cmac v0.0.0-20160719120800-7af84192f0b1 // indirect
3333
github.com/antonfisher/nested-logrus-formatter v1.3.1 // indirect
3434
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
35+
github.com/goccy/go-yaml v1.15.23 // indirect
3536
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
3637
github.com/khirono/go-genl v1.0.1 // indirect
3738
github.com/pkg/errors v0.9.1 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
1313
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1414
github.com/free5gc/aper v1.0.5 h1:sUYFFmOXDLjyL4rU6zFnq81M4YluqP90Pso5e/J4UhA=
1515
github.com/free5gc/aper v1.0.5/go.mod h1:ybHxhYnRqQ9wD4yB9r/3MZdbCYCjtqUyfLpSnJpwWd4=
16-
github.com/free5gc/go-gtp5gnl v1.4.6 h1:xqwyGjrRNRGwo3/HyfXMh/fQ56QnCUzQKP2XR5/i1cE=
17-
github.com/free5gc/go-gtp5gnl v1.4.6/go.mod h1:TT5aXB90NuSPMehuIK9lV2yJFnq6Qjw37ZqNB1QAKh0=
1816
github.com/free5gc/go-gtp5gnl v1.4.7-0.20241008130314-a3088e4cb7fa h1:D5OzFSttS6WY2XRspxtPKoHyCVkRLH9kqteQ1bGfOg0=
1917
github.com/free5gc/go-gtp5gnl v1.4.7-0.20241008130314-a3088e4cb7fa/go.mod h1:TT5aXB90NuSPMehuIK9lV2yJFnq6Qjw37ZqNB1QAKh0=
2018
github.com/free5gc/nas v1.1.3 h1:eYkvT8GGieD06MExw3JLeIPA88Yg89DFjptVBnadIyQ=
@@ -39,6 +37,8 @@ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg
3937
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
4038
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
4139
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
40+
github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo=
41+
github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
4242
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
4343
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
4444
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=

0 commit comments

Comments
 (0)