1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
// Copyright (c) 2017-2020 Ivaylo Petrov
//
// Licensed under the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
//
// author: Ivaylo Petrov <ivajloip@gmail.com>
use super::parser::EUI64;
use super::securityhelpers::generic_array::{typenum::U16, GenericArray};
macro_rules! lorawan_key {
(
$(#[$outer:meta])*
pub struct $type:ident(AES128);
) => {
$(#[$outer])*
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct $type(pub(crate) AES128);
impl From<[u8;16]> for $type {
fn from(key: [u8; 16]) -> Self {
$type(AES128(key))
}
}
impl $type {
pub fn inner(&self) -> &AES128 {
&self.0
}
}
};
}
lorawan_key!(
/// AppKey should be entered in MSB format. For example, if your LNS provides a AppKey of
/// `00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF`, you should enter it as `AppKey([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF])`.
pub struct AppKey(AES128);
);
lorawan_key!(
/// NwkSKey should be entered in MSB format. For example, if your LNS provides a NwkSKey of
/// `00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF`, you should enter it as `NwkSKey([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF])`.
pub struct NewSKey(AES128);
);
lorawan_key!(
/// AppSKey should be entered in MSB format. For example, if your LNS provides a AppSKey of
/// `00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF`, you should enter it as `AppSKey([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF])`.
pub struct AppSKey(AES128);
);
macro_rules! lorawan_eui {
(
$(#[$outer:meta])*
pub struct $type:ident(EUI64<[u8; 8]>);
) => {
$(#[$outer])*
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct $type(EUI64<[u8; 8]>);
impl From<[u8;8]> for $type {
fn from(key: [u8; 8]) -> Self {
$type(EUI64::from(key))
}
}
impl From<$type> for EUI64<[u8; 8]> {
fn from(key: $type) -> Self {
key.0
}
}
};
}
lorawan_eui!(
/// DevEui should be entered in LSB format. For example, if your LNS provides a DevEui of
/// `00:11:22:33:44:55:66:77`, you should enter it as `DevEui([0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00])`.
pub struct DevEui(EUI64<[u8; 8]>);
);
lorawan_eui!(
/// AppEui should be entered in LSB format. For example, if your LNS provides a AppEui of
/// `00:11:22:33:44:55:66:77`, you should enter it as `AppEui([0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00])`.
pub struct AppEui(EUI64<[u8; 8]>);
);
/// AES128 represents 128-bit AES key.
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub struct AES128(pub [u8; 16]);
impl From<[u8; 16]> for AES128 {
fn from(v: [u8; 16]) -> Self {
AES128(v)
}
}
/// MIC represents LoRaWAN MIC.
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub struct MIC(pub [u8; 4]);
impl From<[u8; 4]> for MIC {
fn from(v: [u8; 4]) -> Self {
MIC(v)
}
}
/// Trait for implementations of AES128 encryption.
pub trait Encrypter {
fn encrypt_block(&self, block: &mut GenericArray<u8, U16>);
}
/// Trait for implementations of AES128 decryption.
pub trait Decrypter {
fn decrypt_block(&self, block: &mut GenericArray<u8, U16>);
}
/// Trait for implementations of CMAC.
pub trait Mac {
fn input(&mut self, data: &[u8]);
fn reset(&mut self);
fn result(self) -> GenericArray<u8, U16>;
}
/// Represents an abstraction over the crypto functions.
///
/// This trait provides a way to pick a different implementation of the crypto primitives.
pub trait CryptoFactory {
type E: Encrypter;
type D: Decrypter;
type M: Mac;
/// Method that creates an Encrypter.
fn new_enc(&self, key: &AES128) -> Self::E;
/// Method that creates a Decrypter.
fn new_dec(&self, key: &AES128) -> Self::D;
/// Method that creates a MAC calculator.
fn new_mac(&self, key: &AES128) -> Self::M;
}