A fast, memory-safe library for encoding and decoding 5G NAS (Non-Access Stratum) messages in Rust, per 3GPP TS 24.501.
Part of the OxiRush project — a 5G Core Network testing framework.
- Complete 5G NAS codec — all 5GMM and 5GSM message types from TS 24.501
- 100+ Information Elements — full TLV/TV/V/LV wire-format codec via
Encode/Decodetraits - Typed IE accessors — zero-cost enums and builder helpers over raw bytes (no manual bit manipulation)
- Human-readable display — Wireshark-style
fmt::Displayfor all messages - Structural validation helpers — core TS 24.501 checks with error/warning severity levels
- NAS security envelope (optional) — integrity + ciphering per TS 33.501, with NAS COUNT tracking
- Serde support (optional) — JSON serialization for typed IE structs
- Round-trip preservation — decode then re-encode preserves supported fields and unknown IE payloads, with byte-exact coverage verified by the test suite
[dependencies]
oxirush-nas = "0.3"| Feature | Description |
|---|---|
security |
NAS security envelope (protect/unprotect) via oxirush-security |
serde |
JSON serialization with serde::Serialize/Deserialize |
oxirush-nas = { version = "0.3", features = ["security", "serde"] }use oxirush_nas::{decode_nas_5gs_message, encode_nas_5gs_message, Validate};
// Decode a Registration Request from raw bytes
let bytes = hex::decode(
"7e004179000d0199f9070000000000000010022e08a020000000000000"
).unwrap();
let msg = decode_nas_5gs_message(&bytes).unwrap();
// Wireshark-style display
println!("{msg}");
// => 5GMM RegistrationRequest (Initial) SUCI: 208-93-0000000000 ...
// Structural validation helpers for common TS 24.501 rules
assert!(msg.validate().is_empty());
// Round-trip encode
assert_eq!(bytes, encode_nas_5gs_message(&msg).unwrap());use oxirush_nas::{decode_nas_5gs_message, Nas5gsMessage, Nas5gmmMessage};
use oxirush_nas::ie::*;
let bytes = hex::decode(
"7e004179000d0199f9070000000000000010022e08a020000000000000"
).unwrap();
let msg = decode_nas_5gs_message(&bytes).unwrap();
if let Nas5gsMessage::Gmm(_, Nas5gmmMessage::RegistrationRequest(reg)) = &msg {
// Registration type as a typed enum
assert_eq!(reg.fgs_registration_type.registration_type(),
Some(RegistrationType::InitialRegistration));
// Mobile identity variant
assert_eq!(reg.fgs_mobile_identity.identity_type(),
Some(MobileIdentityType::Suci));
// Extract PLMN
if let Some(plmn) = reg.fgs_mobile_identity.plmn() {
println!("MCC={}, MNC={}", plmn.mcc_string(), plmn.mnc_string());
}
}use oxirush_nas::ie::GmmCause;
use oxirush_nas::messages::NasRegistrationReject;
use oxirush_nas::*;
// Build a RegistrationReject with cause code
let reject = NasRegistrationReject::new(
NasFGmmCause::from_cause(GmmCause::IllegalUe),
);
let msg = Nas5gsMessage::new_5gmm(Nas5gmmMessage::RegistrationReject(reject));
let wire_bytes = encode_nas_5gs_message(&msg).unwrap();use oxirush_nas::{
Direction, Nas5gmmMessage, Nas5gsMessage, Nas5gsSecurityHeaderType, NasFGmmCause,
NasSecurityContext,
};
use oxirush_nas::ie::{IntegrityAlgorithm, CipheringAlgorithm};
use oxirush_nas::ie::GmmCause;
use oxirush_nas::messages::NasRegistrationReject;
let knas_int = [0u8; 16];
let knas_enc = [0u8; 16];
let msg = Nas5gsMessage::new_5gmm(Nas5gmmMessage::RegistrationReject(
NasRegistrationReject::new(NasFGmmCause::from_cause(GmmCause::IllegalUe)),
));
let mut ctx = NasSecurityContext::new(
knas_int, knas_enc,
IntegrityAlgorithm::NIA2,
CipheringAlgorithm::NEA2,
);
// Protect outbound (integrity + ciphering)
let protected = ctx.protect(
&msg,
Nas5gsSecurityHeaderType::IntegrityProtectedAndCiphered,
Direction::Downlink,
).unwrap();
// Unprotect inbound (MAC verify + decipher + decode)
let (decoded, sht) = ctx.unprotect(&protected, Direction::Downlink).unwrap();
assert_eq!(sht, Nas5gsSecurityHeaderType::IntegrityProtectedAndCiphered);
assert!(matches!(
decoded,
Nas5gsMessage::Gmm(_, Nas5gmmMessage::RegistrationReject(_))
)); +-----------+
| lib.rs | re-exports everything
+-----+-----+
|
+--------+----------+----------+---------+
| | | | |
types.rs messages.rs ie.rs display.rs validate.rs
(Layer 1) (Layer 2) (Layer 3)
| Module | Description |
|---|---|
[types] |
Wire-level codec — Encode/Decode traits, 100+ IE structs (TLV/TV/V/LV formats) |
[messages] |
NAS message structs with IEI dispatch, encode_nas_5gs_message()/decode_nas_5gs_message() |
[ie] |
Typed IE accessors — zero-cost enums, parsers, and builder helpers |
[display] |
fmt::Display implementations for Wireshark-style message formatting |
[validate] |
Structural validation per TS 24.501 (errors + warnings) |
[security] |
NAS security envelope — protect/unprotect with NAS COUNT tracking (feature-gated) |
- Layer 1 (
types) — raw binary IE structs generated by macros. Each struct has apub valuefield and implementsEncode/Decodefor the wire format (V, LV, LV-E, TV, TLV, TLV-E per TS 24.007 §11.2). - Layer 2 (
messages) — NAS message structs generated by thenas_message!macro. Mandatory fields in the constructor, optional fields viaset_*()builder methods. Decode dispatches on IEI bytes. - Layer 3 (
ie) — typed zero-cost wrappers. Enums likeRegistrationType,GmmCause,CipheringAlgorithmreplace manual bit manipulation.from_*()constructors and accessor methods on the raw IE structs.
- TS 24.501 — 5G NAS protocol (message definitions, IE formats, procedures)
- TS 24.007 — IE encoding formats (V, LV, TLV, etc.)
- TS 33.501 — 5G security architecture (NAS security, key derivation, algorithms)
Full API reference: https://docs.rs/oxirush-nas
Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Sign off your commits (
git commit -s) - Open a Pull Request
By contributing to this project, you agree to the Developer Certificate of Origin (DCO). This means that you have the right to submit your contributions and you agree to license them according to the project's license.
All commits should be signed-off with git commit -s to indicate your agreement to the DCO.
Copyright 2025-2026 Valentin D'Emmanuele
Licensed under the Apache License, Version 2.0. See LICENSE for details.
OxiRush is inspired by PacketRusher, reimplemented in Rust for improved performance and safety.