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}