use lorawan::creator::*;
use lorawan::default_crypto::DefaultFactory;
use lorawan::keys::*;
use lorawan::maccommandcreator::*;
use lorawan::maccommands::*;
use lorawan::parser::*;
fn phy_join_request_payload() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0x00, 0x04, 0x03, 0x02, 0x01, 0x04, 0x03, 0x02, 0x01, 0x05, 0x04, 0x03, 0x02, 0x05, 0x04,
0x03, 0x02, 0x2d, 0x10, 0x6a, 0x99, 0x0e, 0x12,
]);
res
}
fn phy_join_accept_payload() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0x20, 0x49, 0x3e, 0xeb, 0x51, 0xfb, 0xa2, 0x11, 0x6f, 0x81, 0x0e, 0xdb, 0x37, 0x42, 0x97,
0x51, 0x42,
]);
res
}
fn phy_join_accept_payload_with_c_f_list() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0x20, 0xe4, 0x56, 0x73, 0xb6, 0x3c, 0xb4, 0xb9, 0xce, 0xcb, 0x2a, 0xa8, 0x3f, 0x03, 0x33,
0xe6, 0x15, 0xd2, 0xac, 0x89, 0xee, 0xa1, 0x65, 0x98, 0x37, 0xc3, 0xaa, 0x6d, 0xf9, 0x68,
0x98, 0x89, 0xcf,
]);
res
}
fn phy_dataup_payload() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0x40, 0x04, 0x03, 0x02, 0x01, 0x80, 0x01, 0x00, 0x01, 0xa6, 0x94, 0x64, 0x26, 0x15, 0xd6,
0xc3, 0xb5, 0x82,
]);
res
}
fn phy_long_dataup_payload() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0x40, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x27, 0x5a, 0xe9, 0x94, 0x2a, 0x58,
0x32, 0x21, 0x48, 0xba, 0xd6, 0xca, 0x7d, 0x74, 0x6e, 0x77, 0x4a, 0xf8, 0x66, 0x7a, 0x7b,
0x72, 0x36, 0x4b, 0xe4, 0xe1, 0x9d, 0x2f, 0x5c, 0x23, 0x98, 0x4f, 0xe2, 0x5e, 0x8e, 0x2d,
0xdb, 0xd5, 0x15, 0xb5, 0x4e, 0xbe, 0x80, 0xce, 0xc2, 0x1c, 0xd6, 0x5a, 0x88, 0x13, 0x0f,
0xbe, 0x6d, 0x04, 0xaa, 0xb2, 0xbc, 0x39, 0xab, 0xbe, 0xd9, 0xe8, 0x73, 0xef, 0xc7, 0x85,
0xe5, 0x65, 0x5d, 0x62, 0x72, 0xf8, 0x79, 0x6b, 0x1e, 0x83, 0x9f, 0x2b, 0x1b, 0xde, 0xab,
0xa2, 0x01, 0x6c, 0x7e, 0xf9, 0x16, 0x9d, 0x51, 0xf4, 0xea, 0x26, 0x1b, 0xc6, 0x08, 0x9c,
0x83, 0xb3, 0x3c, 0x6f, 0x30, 0xa7, 0x3c, 0xe1, 0x3c, 0x52, 0x55, 0x7c, 0x46, 0xd7, 0x91,
0xe7, 0xe0, 0x1b, 0x39, 0xe0, 0xb8, 0x9c, 0x1d, 0x2e, 0x35, 0x08, 0x84, 0x1b, 0x67, 0xe3,
0xec, 0x88, 0x6f, 0x96, 0xeb, 0x0e, 0x11, 0x16, 0x40, 0xd3, 0xc1, 0x94, 0xf1, 0x21, 0x49,
0xab, 0x58, 0x4b, 0xd9, 0x31, 0xdc, 0x15, 0xfc, 0x11, 0x94, 0x97, 0xdc, 0xcb, 0xf2, 0xb5,
0xb9, 0x16, 0xb8, 0x52, 0x42, 0x96, 0x33, 0x41, 0xa5, 0x8b, 0xb5, 0x87, 0x7b, 0xd5, 0xaf,
0x9e, 0xe4, 0x2d, 0x8b, 0x6f, 0x48, 0x45, 0x85, 0xa6, 0xf9, 0xcb, 0xaf, 0xf7, 0x2e, 0xe1,
0x09, 0x42, 0xe1, 0x23, 0x8c, 0x98, 0xd7, 0xbf, 0xe7, 0xca, 0x0b, 0x2d, 0xb2, 0x24, 0x8d,
0xb9, 0x1c, 0xd2, 0x3a, 0x71, 0xc6, 0xdb, 0x9b, 0x76, 0x8c, 0xf7, 0xef, 0x17, 0xf0, 0x51,
0xcf, 0x42, 0x3e, 0x73, 0x47, 0x7a, 0xbc, 0x9b, 0x0f, 0xf0, 0x62, 0xde, 0x1e, 0x85, 0x20,
0x29, 0x92, 0xdd, 0xca, 0x58, 0x37, 0x44, 0x19, 0x0c, 0x4f, 0xf7, 0xe1, 0xb4, 0x2e, 0xa3,
0xcc,
]);
res
}
fn long_data_payload() -> String {
String::from(
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor \
invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et \
accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, not",
)
}
fn phy_datadown_payload() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0xa0, 0x04, 0x03, 0x02, 0x01, 0x80, 0xff, 0x2a, 0x2a, 0x0a, 0xf1, 0xa3, 0x6a, 0x05, 0xd0,
0x12, 0x5f, 0x88, 0x5d, 0x88, 0x1d, 0x49, 0xe1,
]);
res
}
fn data_payload_with_fport_zero() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0x40, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x69, 0x36, 0x9e, 0xee, 0x6a, 0xa5,
0x08,
]);
res
}
fn data_payload_with_f_opts() -> Vec<u8> {
let mut res = Vec::new();
res.extend_from_slice(&[
0x40, 0x04, 0x03, 0x02, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x05, 0xd7, 0xfa, 0x0c, 0x6c,
]);
res
}
fn app_key() -> [u8; 16] {
[0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
}
#[test]
fn test_mhdr_mtype() {
let examples = [
(0x00, MType::JoinRequest),
(0x20, MType::JoinAccept),
(0x40, MType::UnconfirmedDataUp),
(0x60, MType::UnconfirmedDataDown),
(0x80, MType::ConfirmedDataUp),
(0xa0, MType::ConfirmedDataDown),
(0xc0, MType::RFU),
(0xe0, MType::Proprietary),
];
for (v, expected) in &examples {
let mhdr = MHDR::new(*v);
assert_eq!(mhdr.mtype(), *expected);
}
}
#[test]
fn test_mhdr_major() {
let examples = [(0, Major::LoRaWANR1), (1, Major::RFU)];
for (v, expected) in &examples {
let mhdr = MHDR::new(*v);
assert_eq!(mhdr.major(), *expected);
}
}
#[test]
fn test_parse_phy_payload_with_too_few_bytes_is_err() {
let bytes = [0x80, 0x04, 0x03, 0x02, 0x01, 0x00, 0xff, 0x01, 0x02, 0x03, 0x04];
let phy = parse(bytes);
assert!(phy.is_err());
}
#[test]
fn test_parse_phy_payload_with_unsupported_major_versoin() {
let bytes = [0x81, 0x04, 0x03, 0x02, 0x01, 0x00, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05];
let phy = parse(bytes);
assert_eq!(phy.err(), Some(lorawan::parser::Error::UnsupportedMajorVersion));
}
#[test]
fn test_parse_join_request_payload() {
let phy = parse(phy_join_request_payload());
assert_eq!(
phy,
Ok(PhyPayload::JoinRequest(JoinRequestPayload::new(phy_join_request_payload()).unwrap()))
);
}
#[test]
fn test_parse_join_accept_payload() {
let phy = parse(phy_join_accept_payload());
assert_eq!(
phy,
Ok(PhyPayload::JoinAccept(JoinAcceptPayload::Encrypted(
EncryptedJoinAcceptPayload::new(phy_join_accept_payload()).unwrap()
)))
);
}
#[test]
fn test_parse_data_payload() {
let phy = parse(phy_dataup_payload());
assert_eq!(
phy,
Ok(PhyPayload::Data(DataPayload::Encrypted(
EncryptedDataPayload::new(phy_dataup_payload()).unwrap()
)))
);
}
#[test]
fn test_parse_data_payload_no_panic_when_bad_packet() {
let data = [0x40, 0x04, 0x03, 0x02, 0x01, 0x85, 0x01, 0x00, 0xd6, 0xc3, 0xb5, 0x82];
let phy = parse(data);
assert_eq!(phy.err(), Some(lorawan::parser::Error::InvalidData));
}
#[test]
fn test_parse_data_payload_no_panic_when_too_short_packet() {
let data = [0x40, 0x04, 0x03, 0x02, 0x01];
let phy = EncryptedDataPayload::new(data);
assert_eq!(phy.err(), Some(lorawan::parser::Error::InvalidData));
}
#[test]
fn test_new_join_accept_payload_too_short() {
let mut bytes = phy_join_accept_payload();
let key = app_key().into();
let len = bytes.len();
assert!(DecryptedJoinAcceptPayload::new(&mut bytes[..(len - 1)], &key).is_err());
}
#[test]
fn test_new_join_accept_payload_mic_validation() {
let decrypted_phy = new_decrypted_join_accept();
assert!(decrypted_phy.validate_mic(&[1; 16].into()));
}
fn new_decrypted_join_accept() -> DecryptedJoinAcceptPayload<Vec<u8>, DefaultFactory> {
let data = phy_join_accept_payload_with_c_f_list();
let key = [1; 16].into();
DecryptedJoinAcceptPayload::new(data, &key).unwrap()
}
#[test]
fn test_new_join_accept_c_f_list_empty() {
let data = phy_join_accept_payload();
let key = app_key().into();
let decrypted_phy = DecryptedJoinAcceptPayload::new(data, &key).unwrap();
assert_eq!(decrypted_phy.c_f_list(), None);
}
#[test]
fn test_join_accept_app_nonce_extraction() {
let decrypted_phy = new_decrypted_join_accept();
let expected = [3, 2, 1];
assert_eq!(decrypted_phy.app_nonce(), AppNonce::new(&expected[..]).unwrap());
}
#[test]
fn test_join_accept_rx_delay_extraction() {
let decrypted_phy = new_decrypted_join_accept();
assert_eq!(decrypted_phy.rx_delay(), 3);
}
#[test]
fn test_join_accept_dl_settings_extraction() {
let decrypted_phy = new_decrypted_join_accept();
assert_eq!(decrypted_phy.dl_settings(), DLSettings::new(0x12));
}
#[test]
fn test_dl_settings() {
let dl_settings = DLSettings::new(0xcb);
assert_eq!(dl_settings.rx1_dr_offset(), 4);
assert_eq!(dl_settings.rx2_data_rate(), 11);
}
#[test]
fn test_new_join_accept_payload_with_c_f_list() {
let data = phy_join_accept_payload_with_c_f_list();
let key = [1; 16].into();
let decrypted_phy = DecryptedJoinAcceptPayload::new(data, &key).unwrap();
let expected_c_f_list = CfList::DynamicChannel([
Frequency::new_from_raw(&[0x18, 0x4F, 0x84]),
Frequency::new_from_raw(&[0xE8, 0x56, 0x84]),
Frequency::new_from_raw(&[0xB8, 0x5E, 0x84]),
Frequency::new_from_raw(&[0x88, 0x66, 0x84]),
Frequency::new_from_raw(&[0x58, 0x6E, 0x84]),
]);
assert_eq!(decrypted_phy.c_f_list(), Some(expected_c_f_list));
}
#[test]
fn test_mic_extraction() {
let bytes = &phy_dataup_payload()[..];
let phy = EncryptedDataPayload::new(bytes);
assert_eq!(phy.unwrap().mic(), MIC([0xd6, 0xc3, 0xb5, 0x82]));
}
#[test]
fn test_validate_data_mic_when_ok() {
let phy = EncryptedDataPayload::new(phy_dataup_payload()).unwrap();
let key = AES128([2; 16]);
assert!(phy.validate_mic(&key, 1));
}
#[test]
fn test_validate_data_mic_when_not_ok() {
let mut bytes = phy_dataup_payload();
bytes[8] = 0xee;
let phy = EncryptedDataPayload::new(bytes).unwrap();
let key = AES128([2; 16]);
assert!(!phy.validate_mic(&key, 1));
}
#[test]
fn test_new_data_payload_is_none_if_bytes_too_short() {
let bytes = &[0x80, 0x04, 0x03, 0x02, 0x01, 0x00, 0xff, 0x01, 0x02, 0x03, 0x04];
let bytes_with_fopts =
&[0x00, 0x04, 0x03, 0x02, 0x01, 0x01, 0xff, 0x04, 0x01, 0x02, 0x03, 0x04];
assert!(EncryptedDataPayload::new(bytes).is_err());
assert!(EncryptedDataPayload::new(bytes_with_fopts).is_err());
}
#[test]
fn test_f_port_could_be_absent_in_data_payload() {
let bytes = &[0x80, 0x04, 0x03, 0x02, 0x01, 0x00, 0xff, 0x04, 0x01, 0x02, 0x03, 0x04];
let data_payload = EncryptedDataPayload::new(bytes).unwrap();
assert!(data_payload.f_port().is_none());
}
#[test]
fn test_complete_data_payload_fhdr() {
let app_skey = AES128([1; 16]);
let nwk_skey = AES128([2; 16]);
let phys: [Box<dyn DataHeader>; 2] = [
Box::new(EncryptedDataPayload::new(phy_dataup_payload()).unwrap()),
Box::new(
DecryptedDataPayload::new(phy_dataup_payload(), &nwk_skey, Some(&app_skey), 1).unwrap(),
),
];
for phy in phys {
assert_eq!(phy.f_port(), Some(1));
let fhdr = phy.fhdr();
assert_eq!(fhdr.dev_addr(), DevAddr::new([4, 3, 2, 1]).unwrap());
assert_eq!(fhdr.fcnt(), 1u16);
let fctrl = fhdr.fctrl();
assert_eq!(fctrl.f_opts_len(), 0);
assert!(!fctrl.f_pending(), "no f_pending");
assert!(!fctrl.ack(), "no ack");
assert!(fctrl.adr(), "ADR");
}
}
#[test]
fn test_complete_dataup_payload_frm_payload() {
let phy = EncryptedDataPayload::new(phy_dataup_payload()).unwrap();
let key = AES128([1; 16]);
let decrypted = phy.decrypt(None, Some(&key), 1).unwrap();
let mut payload = Vec::new();
payload.extend_from_slice(&String::from("hello").into_bytes()[..]);
assert_eq!(decrypted.frm_payload(), FRMPayload::Data(&payload));
}
#[test]
fn test_complete_long_dataup_payload_frm_payload() {
let phy = EncryptedDataPayload::new(phy_long_dataup_payload()).unwrap();
let nwk_skey = AES128([2; 16]);
let app_skey = AES128([1; 16]);
let decrypted = phy.decrypt_if_mic_ok(&nwk_skey, &app_skey, 0).unwrap();
let mut payload = Vec::new();
payload.extend_from_slice(&long_data_payload().into_bytes()[..]);
assert_eq!(decrypted.frm_payload(), FRMPayload::Data(&payload));
}
#[test]
fn test_complete_datadown_payload_frm_payload() {
let phy = EncryptedDataPayload::new(phy_datadown_payload()).unwrap();
let key = AES128([1; 16]);
let decrypted = phy.decrypt(None, Some(&key), 76543).unwrap();
let mut payload = Vec::new();
payload.extend_from_slice(&String::from("hello lora").into_bytes()[..]);
assert_eq!(decrypted.frm_payload(), FRMPayload::Data(&payload));
}
#[test]
fn test_mac_command_in_downlink() {
let data = [
0x60, 0x5f, 0x3b, 0xd7, 0x4e, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x03, 0x00,
0xff, 0x00, 0x30, 0xcd, 0xdb, 0x22, 0xee,
];
let packet = EncryptedDataPayload::new(data).unwrap();
assert_eq!(packet.mhdr().mtype(), MType::UnconfirmedDataDown);
let fhdr = packet.fhdr();
let fopts: Vec<_> = MacCommandIterator::<DownlinkMacCommand>::new(fhdr.data()).collect();
assert_eq!(fopts.len(), 2);
for cmd in fopts.iter() {
match cmd {
DownlinkMacCommand::LinkADRReq(_) => (),
_ => panic!("incorrect payload type: {:?}", cmd),
}
}
}
#[test]
fn test_decrypt_downlink_missing_f_port_bug() {
let encrypted_payload = EncryptedDataPayload::new([
0x60, 0x0, 0x0, 0x0, 0x48, 0xa, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x70, 0x3, 0x0, 0x0, 0xff,
0x0, 0xfc, 0x68, 0xf4, 0x5e,
])
.unwrap();
let key = AES128([1; 16]);
let fcnt = 0;
assert!(encrypted_payload.decrypt(Some(&key), None, fcnt as u32).is_ok());
}
#[test]
fn test_new_frequency() {
let freq = Frequency::new(&[0x18, 0x4F, 0x84]);
assert!(freq.is_some());
assert_eq!(freq.unwrap().value(), 867_100_000);
}
#[test]
fn test_fctrl_uplink_complete() {
let byte = 0xff;
let uplink_fctrl = FCtrl::new(byte, true);
assert!(uplink_fctrl.ack());
assert!(uplink_fctrl.adr());
assert!(uplink_fctrl.adr_ack_req());
assert_eq!(uplink_fctrl.f_opts_len(), 15);
assert_eq!(uplink_fctrl.raw_value(), byte);
}
#[test]
fn test_fctrl_downlink_complete() {
let downlink_fctrl = FCtrl::new(0xff, false);
assert!(downlink_fctrl.f_pending());
}
#[test]
fn test_data_payload_uplink_creator() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [2; 16].into();
let app_skey = [1; 16].into();
let fctrl = FCtrl::new(0x80, true);
phy.set_confirmed(false)
.set_uplink(true)
.set_f_port(1)
.set_dev_addr(&[4, 3, 2, 1])
.set_fctrl(&fctrl) .set_fcnt(1);
assert_eq!(phy.build(b"hello", &[], &nwk_skey, &app_skey).unwrap(), &phy_dataup_payload()[..]);
}
#[test]
fn test_long_data_payload_uplink_creator() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [2; 16].into();
let app_skey = [1; 16].into();
let fctrl = FCtrl::new(0x00, true);
phy.set_confirmed(false)
.set_uplink(true)
.set_f_port(1)
.set_dev_addr(&[4, 3, 2, 1])
.set_fctrl(&fctrl) .set_fcnt(0);
assert_eq!(
phy.build(&long_data_payload().into_bytes()[..], &[], &nwk_skey, &app_skey).unwrap(),
&phy_long_dataup_payload()[..]
);
}
#[test]
fn test_data_payload_downlink_creator() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [2; 16].into();
let app_skey = [1; 16].into();
let fctrl = FCtrl::new(0x80, false);
phy.set_confirmed(true)
.set_uplink(false)
.set_f_port(42)
.set_dev_addr(&[4, 3, 2, 1])
.set_fctrl(&fctrl) .set_fcnt(76543);
assert_eq!(
phy.build(b"hello lora", &[], &nwk_skey, &app_skey).unwrap(),
&phy_datadown_payload()[..]
);
}
#[test]
fn test_data_payload_creator_when_payload_and_fport_0() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [2; 16].into();
let app_skey = [1; 16].into();
phy.set_f_port(0);
assert!(phy.build(b"hello", &[], &nwk_skey, &app_skey).is_err());
}
#[test]
fn test_data_payload_creator_when_encrypt_but_not_fport_0() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [2; 16].into();
let app_skey = [1; 16].into();
let new_channel_req =
DownlinkMacCommand::NewChannelReq(NewChannelReqPayload::new_from_raw(&[0x00; 5]));
let mut cmds: Vec<&dyn SerializableMacCommand> = Vec::new();
cmds.extend_from_slice(&[&new_channel_req, &new_channel_req, &new_channel_req]);
phy.set_f_port(1);
assert!(phy.build(b"", &cmds[..], &nwk_skey, &app_skey).is_err());
}
#[test]
fn test_data_payload_creator_when_payload_no_fport() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [2; 16].into();
let app_skey = [1; 16].into();
assert!(phy.build(b"hello", &[], &nwk_skey, &app_skey).is_err());
}
#[test]
fn test_data_payload_creator_when_mac_commands_in_payload() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [1; 16].into();
let app_skey = [0; 16].into();
let mac_cmd1 = UplinkMacCommand::LinkCheckReq(LinkCheckReqPayload());
let mut mac_cmd2 = LinkADRAnsCreator::new();
mac_cmd2.set_channel_mask_ack(true).set_data_rate_ack(false).set_tx_power_ack(true);
let mut cmds: Vec<&dyn SerializableMacCommand> = Vec::new();
cmds.extend_from_slice(&[&mac_cmd1, &mac_cmd2]);
phy.set_confirmed(false).set_uplink(true).set_f_port(0).set_dev_addr(&[4, 3, 2, 1]).set_fcnt(0);
assert_eq!(
phy.build(b"", &cmds[..], &nwk_skey, &app_skey).unwrap(),
&data_payload_with_fport_zero()[..]
);
}
#[test]
fn test_data_payload_creator_when_mac_commands_in_f_opts() {
let mut phy = DataPayloadCreator::new();
let nwk_skey = [1; 16].into();
let app_skey = [0; 16].into();
let mac_cmd1 = UplinkMacCommand::LinkCheckReq(LinkCheckReqPayload());
let mut mac_cmd2 = LinkADRAnsCreator::new();
mac_cmd2.set_channel_mask_ack(true).set_data_rate_ack(false).set_tx_power_ack(true);
let mut cmds: Vec<&dyn SerializableMacCommand> = Vec::new();
cmds.extend_from_slice(&[&mac_cmd1, &mac_cmd2]);
phy.set_confirmed(false).set_uplink(true).set_dev_addr(&[4, 3, 2, 1]).set_fcnt(0);
assert_eq!(
phy.build(b"", &cmds[..], &nwk_skey, &app_skey).unwrap(),
&data_payload_with_f_opts()[..]
);
}
#[test]
fn test_join_request_dev_eui_extraction() {
let data = phy_join_request_payload();
let join_request = JoinRequestPayload::new(&data[..]).unwrap();
assert_eq!(join_request.dev_eui(), EUI64::new(&data[9..17]).unwrap());
}
#[test]
fn test_join_request_app_eui_extraction() {
let data = phy_join_request_payload();
let join_request = JoinRequestPayload::new(&data[..]).unwrap();
assert_eq!(join_request.app_eui(), EUI64::new(&data[1..9]).unwrap());
}
#[test]
fn test_join_request_dev_nonce_extraction() {
let data = phy_join_request_payload();
let join_request = JoinRequestPayload::new(&data[..]).unwrap();
assert_eq!(join_request.dev_nonce(), DevNonce::new(&data[17..19]).unwrap());
}
#[test]
fn test_validate_join_request_mic_when_ok() {
let data = phy_join_request_payload();
let join_request = JoinRequestPayload::new(&data[..]).unwrap();
let key = AES128([1; 16]);
assert!(join_request.validate_mic(&key));
}
#[test]
fn test_validate_join_request_mic_when_not_ok() {
let data = phy_join_request_payload();
let join_request = JoinRequestPayload::new(&data[..]).unwrap();
let key = AES128([2; 16]);
assert!(!join_request.validate_mic(&key));
}
#[test]
#[cfg(feature = "default-crypto,with-downlink")]
fn test_join_accept_creator() {
let mut phy = JoinAcceptCreator::new();
let key = AES128(app_key());
let app_nonce_bytes = [0xc7, 0x0b, 0x57];
phy.set_app_nonce(&app_nonce_bytes)
.set_net_id(&[0x01, 0x11, 0x22])
.set_dev_addr(&[0x80, 0x19, 0x03, 0x02])
.set_dl_settings(0)
.set_rx_delay(0);
assert_eq!(phy.build(&key), &phy_join_accept_payload()[..]);
}
#[test]
fn test_join_request_creator() {
let mut phy = JoinRequestCreator::new();
let key = [1; 16].into();
phy.set_app_eui(&[0x04, 0x03, 0x02, 0x01, 0x04, 0x03, 0x02, 0x01])
.set_dev_eui(&[0x05, 0x04, 0x03, 0x02, 0x05, 0x04, 0x03, 0x02])
.set_dev_nonce(&[0x2du8, 0x10]);
assert_eq!(phy.build(&key), &phy_join_request_payload()[..]);
}
#[test]
fn test_join_request_creator_with_options() {
let mut data = [0; 23];
{
let mut phy = JoinRequestCreator::with_options(&mut data[..], DefaultFactory).unwrap();
let key = [1; 16].into();
phy.set_app_eui(&[0x04, 0x03, 0x02, 0x01, 0x04, 0x03, 0x02, 0x01])
.set_dev_eui(&[0x05, 0x04, 0x03, 0x02, 0x05, 0x04, 0x03, 0x02])
.set_dev_nonce(&[0x2du8, 0x10]);
assert_eq!(phy.build(&key), &phy_join_request_payload()[..]);
}
assert_eq!(&data[..], &phy_join_request_payload()[..]);
}
#[test]
fn test_derive_newskey() {
let key = AppKey::from(app_key());
let join_request = JoinRequestPayload::new(phy_join_request_payload()).unwrap();
let join_accept = DecryptedJoinAcceptPayload::new(phy_join_accept_payload(), &key).unwrap();
let newskey = join_accept.derive_newskey(&join_request.dev_nonce(), &key);
let expect = NewSKey::from([
0x7b, 0xb2, 0x5f, 0x89, 0xe0, 0xd1, 0x37, 0x1e, 0x1f, 0xbf, 0x4d, 0x99, 0x7e, 0x14, 0x68,
0xa3,
]);
assert_eq!(newskey, expect);
}
#[test]
fn test_derive_appskey() {
let key = app_key().into();
let join_request = JoinRequestPayload::new(phy_join_request_payload()).unwrap();
let join_accept = DecryptedJoinAcceptPayload::new(phy_join_accept_payload(), &key).unwrap();
let appskey = join_accept.derive_appskey(&join_request.dev_nonce(), &key);
let expect = AppSKey::from([
0x14, 0x88, 0x20, 0xdf, 0xb1, 0xe0, 0xc9, 0xd6, 0x28, 0x9c, 0xde, 0x16, 0xc1, 0xaf, 0x24,
0x9f,
]);
assert_eq!(appskey, expect);
}
#[test]
#[cfg(feature = "with-to-string")]
fn test_eui64_to_string() {
let eui = EUI64::new(&[0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff]).unwrap();
assert_eq!(eui.to_string(), "123456789abcdeff".to_owned());
}