pub struct Data {
pub direction: Direction,
pub confirmed: bool,
pub dev_addr: DevAddr,
pub f_ctrl: FCtrl,
pub f_cnt: [u8; 2],
pub f_opts: Vec<u8>,
pub f_port: Option<u8>,
pub frm_payload: Option<Vec<u8>>,
}Expand description
Fields of a Data message (confirmed or unconfirmed, uplink or downlink).
FRMPayload is encrypted on the wire; call
Data::decrypt_payload to recover the plaintext. MAC commands in
FOpts are encrypted only in LoRaWAN 1.1; call
Data::decrypt_fopts when applicable.
§Frame counters
The wire carries only the lower 16 bits of the 32-bit FCnt. The caller
tracks the upper 16 bits and passes it to Data::f_cnt_32 and to
every crypt / MIC call. Pass 0 for sessions that never wrap.
Fields§
§direction: DirectionFrame direction, inferred from MType.
confirmed: booltrue for ConfirmedData{Up,Down}.
dev_addr: DevAddrDevice address.
f_ctrl: FCtrlFrame-control byte.
f_cnt: [u8; 2]Lower 16 bits of FCnt as on the wire (little-endian).
Use Data::f_cnt for a u16 value or Data::f_cnt_32 for the
full 32-bit counter with a caller-supplied upper half.
f_opts: Vec<u8>MAC commands carried in FOpts (empty when none); up to 15 bytes.
Encrypted with NwkSEncKey in 1.1; plaintext in 1.0.
f_port: Option<u8>FPort byte. Some(0) means FRMPayload carries MAC commands;
Some(p) with p > 0 means application data; None when neither
FPort nor FRMPayload is present.
frm_payload: Option<Vec<u8>>FRMPayload. Encrypted on the wire; replace with plaintext after
Data::decrypt_payload.
Implementations§
Source§impl Data
impl Data
Sourcepub const fn f_cnt(&self) -> u16
pub const fn f_cnt(&self) -> u16
Lower 16 bits of FCnt as read from the wire (little-endian).
The wire stores only the bottom 16 bits of the actual 32-bit counter.
For the full counter use Data::f_cnt_32 together with a
caller-tracked upper half.
Sourcepub const fn f_cnt_32(&self, msb: u16) -> u32
pub const fn f_cnt_32(&self, msb: u16) -> u32
Full 32-bit FCnt, combining the wire LSB16 with a caller-tracked MSB16.
msb is the upper 16 bits the caller has been tracking. Pass 0 if
frame counters never wrap in your deployment; otherwise increment
msb each time the wire counter rolls over from 0xFFFF to 0x0000.
Source§impl Data
impl Data
Sourcepub fn decrypt_payload(
&self,
app_s_key: &AppSKey,
nwk_s_key: &NwkSKey,
f_cnt_msb: u16,
) -> Result<Vec<u8>>
pub fn decrypt_payload( &self, app_s_key: &AppSKey, nwk_s_key: &NwkSKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>
Decrypt FRMPayload.
LoRaWAN uses an AES-CTR-like keystream so the same operation works
in both directions; this method is named for the typical use (receiver
side). The key is selected by FPort:
FPort == 0:NwkSKey(MAC commands inFRMPayload).FPort > 0:AppSKey(application data).
f_cnt_msb is the upper 16 bits of the 32-bit FCnt; pass 0 if
frame counters never wrap. See crate::Data::f_cnt_32.
§Errors
crate::Error::PayloadTooLarge if the ciphertext exceeds the
AES-CTR block-index limit (255 blocks = 4080 bytes).
§Examples
use lora_packet::{LoraPacket, AppSKey, NwkSKey};
let bytes = hex::decode("40f17dbe4900020001954378762b11ff0d")?;
let packet = LoraPacket::from_wire(&bytes)?;
let app_s_key = AppSKey::from_slice(&hex::decode("ec925802ae430ca77fd3dd73cb2cc588")?)?;
let nwk_s_key = NwkSKey::from_slice(&hex::decode("44024241ed4ce9a68c6a8bc055233fd3")?)?;
let plain = packet.as_data().unwrap().decrypt_payload(&app_s_key, &nwk_s_key, 0)?;
assert_eq!(&plain, b"test");Sourcepub fn encrypt_payload(
&self,
plaintext: &[u8],
app_s_key: &AppSKey,
nwk_s_key: &NwkSKey,
f_cnt_msb: u16,
) -> Result<Vec<u8>>
pub fn encrypt_payload( &self, plaintext: &[u8], app_s_key: &AppSKey, nwk_s_key: &NwkSKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>
Encrypt the given plaintext under the FRMPayload keystream.
Same primitive as Self::decrypt_payload; named differently for
clarity at call sites. Used by
crate::LoraPacketBuilder::sign_and_encrypt for downlink building.
Selects NwkSKey when FPort == 0, AppSKey otherwise.
§Errors
crate::Error::PayloadTooLarge if the plaintext exceeds 4080 bytes
(255 AES blocks). Beyond this, the 1-byte block counter in the Ai
keystream block overflows and silently produces ciphertext no other
LoRaWAN stack can decrypt.
Source§impl Data
impl Data
Sourcepub fn decrypt_fopts(
&self,
nwk_s_enc_key: &NwkSEncKey,
f_cnt_msb: u16,
) -> Result<Vec<u8>>
pub fn decrypt_fopts( &self, nwk_s_enc_key: &NwkSEncKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>
Decrypt FOpts MAC commands (LoRaWAN 1.1 only).
In 1.0, FOpts is plaintext on the wire; this method is a no-op
(but still callable). In 1.1, FOpts is encrypted under
NwkSEncKey with a single AES-ECB block.
Uses the keystream layout from the LoRa Alliance errata
“FCntDwn Usage in FOpts Encryption” (CR v2 r1): when the frame is
a downlink with FPort > 0 the aFCntDown flag selects byte 4 =
0x02; otherwise it is 0x01.
§Errors
Currently infallible; returns Result for forward compatibility.
Sourcepub fn encrypt_fopts(
&self,
nwk_s_enc_key: &NwkSEncKey,
f_cnt_msb: u16,
) -> Result<Vec<u8>>
pub fn encrypt_fopts( &self, nwk_s_enc_key: &NwkSEncKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>
Encrypt FOpts MAC commands (LoRaWAN 1.1 only).
Symmetric to Self::decrypt_fopts; same primitive in both
directions. Use when building a 1.1 frame that carries MAC commands
in FOpts.
§Errors
Currently infallible; returns Result for forward compatibility.