Skip to main content

lorawan/
keys.rs

1use super::parser::EUI64;
2use super::securityhelpers::generic_array::{typenum::U16, GenericArray};
3
4macro_rules! lorawan_key {
5    (
6        $(#[$outer:meta])*
7        pub struct $type:ident(AES128);
8    ) => {
9        $(#[$outer])*
10        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
11        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
13        pub struct $type(pub(crate) AES128);
14
15        impl From<[u8;16]> for $type {
16            fn from(key: [u8; 16]) -> Self {
17                $type(AES128(key))
18            }
19        }
20
21        impl $type {
22            pub fn inner(&self) -> &AES128 {
23                &self.0
24            }
25        }
26
27        impl AsRef<[u8]> for $type {
28            fn as_ref(&self) -> &[u8] {
29                &self.0 .0
30            }
31        }
32    };
33}
34
35lorawan_key!(
36    /// You can construct AppKey from a hex-encoded MSB string or bytes in MSB format.
37    ///
38    /// Typically, a LNS will provide it in a string format such as: `00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF`.
39    ///
40    /// To create from a string:
41    /// ```
42    /// use lorawan::keys::AppKey;
43    /// use core::str::FromStr;
44    ///let appkey = AppKey::from_str("00112233445566778899aabbccddeeff").unwrap();
45    /// ```
46    ///
47    /// To create from a byte array, you should enter the bytes in MSB format:
48    /// ```
49    /// use lorawan::keys::AppKey;
50    /// let appkey = AppKey::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
51    /// ```
52    pub struct AppKey(AES128);
53);
54lorawan_key!(
55    /// You can construct NewSKey from a hex-encoded MSB string or bytes in MSB format.
56    ///
57    /// Typically, a LNS will provide a hex-encoded MSB string such as: `00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF`.
58    ///
59    /// To create from a string:
60    /// ```
61    /// use lorawan::keys::NewSKey;
62    /// use core::str::FromStr;
63    /// let newskey = NewSKey::from_str("00112233445566778899aabbccddeeff").unwrap();
64    /// ```
65    ///
66    /// To create from a byte array, you should enter the bytes in MSB format:
67    /// ```
68    /// use lorawan::keys::NewSKey;
69    /// let newskey = NewSKey::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
70    /// ```
71    pub struct NewSKey(AES128);
72);
73lorawan_key!(
74    /// You can construct AppSKey from a hex-encoded MSB string or bytes in MSB format.
75    ///
76    /// Typically, a LNS will provide a hex-encoded MSB string format such as: `00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF`.
77    ///
78    /// To create from a string:
79    /// ```
80    /// use lorawan::keys::AppSKey;
81    /// use core::str::FromStr;
82    /// let appskey = AppSKey::from_str("00112233445566778899aabbccddeeff").unwrap();
83    /// ```
84    ///
85    /// To create from a byte array, you should enter the bytes in MSB format:
86    /// ```
87    /// use lorawan::keys::AppSKey;
88    /// let appskey = AppSKey::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
89    /// ```
90    pub struct AppSKey(AES128);
91);
92
93macro_rules! lorawan_eui {
94    (
95        $(#[$outer:meta])*
96        pub struct $type:ident(EUI64<[u8; 8]>);
97    ) => {
98        $(#[$outer])*
99        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
100        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
101        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
102        pub struct $type(EUI64<[u8; 8]>);
103
104        impl From<[u8;8]> for $type {
105            fn from(key: [u8; 8]) -> Self {
106                $type(EUI64::from(key))
107            }
108        }
109
110        impl From<$type> for EUI64<[u8; 8]> {
111            fn from(key: $type) -> Self {
112                key.0
113            }
114        }
115
116        impl AsRef<[u8]> for $type {
117            fn as_ref(&self) -> &[u8] {
118                &self.0.as_ref()
119            }
120        }
121    };
122}
123
124lorawan_eui!(
125    /// You can construct DevEui from a hex-encoded MSB string or bytes in LSB format.
126    ///
127    /// Typically, a LNS will provide a hex-encoded MSB string such as: `00:11:22:33:44:55:66:77`.
128    ///
129    /// To create from a string:
130    /// ```
131    /// use lorawan::keys::DevEui;
132    /// use core::str::FromStr;
133    /// let dev_eui = DevEui::from_str("0011223344556677").unwrap();
134    /// ```
135    ///
136    /// To create from a byte array, you should enter the bytes in LSB format:
137    /// ```
138    /// use lorawan::keys::DevEui;
139    /// let dev_eui = DevEui::from([0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00]);
140    /// ```
141    pub struct DevEui(EUI64<[u8; 8]>);
142);
143lorawan_eui!(
144    /// You can construct AppEui from a hex-encoded MSB string or bytes in LSB format.
145    ///
146    /// Typically, a LNS will provide a hex-encoded MSB string such as: `00:11:22:33:44:55:66:77`.
147    ///
148    /// To create from a string:
149    /// ```
150    /// use lorawan::keys::AppEui;
151    /// use core::str::FromStr;
152    /// let app_eui = AppEui::from_str("0011223344556677").unwrap();
153    /// ```
154    ///
155    /// To create from a byte array, you should enter the bytes in LSB format:
156    /// ```
157    /// use lorawan::keys::AppEui;
158    /// let app_eui = AppEui::from([0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00]);
159    /// ```
160    pub struct AppEui(EUI64<[u8; 8]>);
161);
162
163/// AES128 represents 128-bit AES key.
164#[cfg_attr(feature = "defmt", derive(defmt::Format))]
165#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
166#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
167pub struct AES128(pub [u8; 16]);
168
169impl From<[u8; 16]> for AES128 {
170    fn from(v: [u8; 16]) -> Self {
171        AES128(v)
172    }
173}
174
175/// MIC represents LoRaWAN MIC.
176#[cfg_attr(feature = "defmt", derive(defmt::Format))]
177#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
178pub struct MIC(pub [u8; 4]);
179
180impl From<[u8; 4]> for MIC {
181    fn from(v: [u8; 4]) -> Self {
182        MIC(v)
183    }
184}
185
186/// Trait for implementations of AES128 encryption.
187pub trait Encrypter {
188    fn encrypt_block(&self, block: &mut GenericArray<u8, U16>);
189}
190
191/// Trait for implementations of AES128 decryption.
192pub trait Decrypter {
193    fn decrypt_block(&self, block: &mut GenericArray<u8, U16>);
194}
195
196/// Trait for implementations of CMAC.
197pub trait Mac {
198    fn input(&mut self, data: &[u8]);
199    fn reset(&mut self);
200    fn result(self) -> GenericArray<u8, U16>;
201}
202
203/// Represents an abstraction over the crypto functions.
204///
205/// This trait provides a way to pick a different implementation of the crypto primitives.
206pub trait CryptoFactory {
207    type E: Encrypter;
208    type D: Decrypter;
209    type M: Mac;
210
211    /// Method that creates an Encrypter.
212    fn new_enc(&self, key: &AES128) -> Self::E;
213
214    /// Method that creates a Decrypter.
215    fn new_dec(&self, key: &AES128) -> Self::D;
216
217    /// Method that creates a MAC calculator.
218    fn new_mac(&self, key: &AES128) -> Self::M;
219}