MACsec: Refactor API

This commit is contained in:
Yasser Yassine
2025-11-05 12:00:07 -05:00
committed by Kyle Schwarz
parent 30c009fe8f
commit 9ff4bf7d0d
33 changed files with 1542 additions and 1140 deletions
+10 -1
View File
@@ -54,7 +54,16 @@ public:
FixedPointOverflow = 0x1018,
FixedPointPrecision = 0x1019,
SyscallError = 0x1020, // check errno/GetLastError() for details
MACsecSecYLimit = 0x1021,
MACsecSaLimit = 0x1022,
MACsecRuleLimit = 0x1023,
MACsecInvalidSecYIndex = 0x1024,
MACsecInvalidSaIndex = 0x1025,
MACsecInvalidRuleIndex = 0x1026,
MACsecRekeyNotEnabled = 0x1027,
MACsecNotSupported = 0x1028,
MACsecConfigMismatch = 0x1029,
// Device Events
PollingMessageOverflow = 0x2000,
NoSerialNumber = 0x2001, // api
+1 -1
View File
@@ -11,7 +11,7 @@
#include <condition_variable>
#include "icsneo/api/eventmanager.h"
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
#include "icsneo/communication/ringbuffer.h"
#include "icsneo/core/ringbuffer.h"
#include "icsneo/device/founddevice.h"
namespace icsneo {
@@ -1,200 +0,0 @@
#ifndef __MACSECMESSAGE_H__
#define __MACSECMESSAGE_H__
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/packet.h"
#include "icsneo/api/eventmanager.h"
#include <vector>
#include <memory>
#include <array>
#include <cstring>
namespace icsneo {
struct MACsecVLANTag
{
uint16_t vid; /*!< 12 bits */
uint8_t priCfi; /*!< PRI - 3 bits, CFI - 1bit */
};
struct MACsecMPLSOuter
{
uint32_t mplsLabel; /*!< 20 bits */
uint8_t exp; /*!< 3 bits */
};
enum class MACsecPacketType : uint8_t
{
NoVLANOrMPLS = 0,
SingleVLAN = 1,
DualVLAN = 2,
MPLS = 3,
SingleVLANFollowedByMPLS = 4,
DualVLANFollowedByMPLS = 5,
Unsupported = 6,
};
struct MACsecRule
{
uint8_t index;
std::array<uint8_t, 6> keyMacDa; /*!< MAC DA field extracted from the packet */
std::array<uint8_t, 6> maskMacDa; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
std::array<uint8_t, 6> keyMacSa; /*!< MAC SA field extracted from the packet */
std::array<uint8_t, 6> maskMacSa; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t keyEthertype; /*!< First E-Type found in the packet that doesn't match one of the preconfigured custom tag. */
uint16_t maskEthertype; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecVLANTag keyVlanTagOuter1; /*!< outermost/1st VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
MACsecMPLSOuter keyMplsOuter1;
MACsecVLANTag maskVlanTagOuter1; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecMPLSOuter maskMplsOuter1;
MACsecVLANTag keyVlanTagOuter2; /*!< 2nd outermost VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
MACsecMPLSOuter keyMplsOuter2;
MACsecVLANTag maskVlanTagOuter2; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecMPLSOuter maskMplsOuter2;
uint16_t keyBonusData; /*!< 2 bytes of additional bonus data extracted from one of the custom tags. */
uint16_t maskBonusData; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t keyTagMatchBitmap; /*!< 8 bits total. Maps 1 to 1 bitwise with the set of custom tags. (set bit[N]=1 if check Nth custom tag) */
uint8_t maskTagMatchBitmap; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecPacketType keyPacketType; /*!< Encoded Packet Type, see MACSEC_PACKET_TYPE */
uint8_t maskPacketType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t keyInnerVlanType; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the second outermost VLAN Tag. */
uint16_t maskInnerVlanType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t keyOuterVlanType; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the outermost VLAN Tag. */
uint16_t maskOuterVlanType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t keyNumTags; /*!< 7 bits total. Number of VLAN/custom tags or MPLS lables detected. Ingress: before SecTag; Egress: total detected. Exclude MCS header tags. i.e. Bit 2: 2 tags/labels before SecTAG...Bit 6: 6 or more tags/labels before SecTAG. */
uint8_t maskNumTags; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
bool keyExpress; /*!< 1 bits. Express packet. */
uint8_t maskExpress; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
bool isMpls;
bool enable;
};
struct MACsecMap
{
uint8_t index;
uint64_t secTagSci; /*!< Identifies the SecTAG SCI for this Flow. */
uint8_t secYIndex; /*!< index for entry in Egress secY Policy */
bool isControlPacket; /*!< Identifies all packets matching this index lookup as control packets. */
uint8_t scIndex; /*!< Identifies the SC for this Flow. */
uint8_t auxiliaryPlcy; /*!< Auxiliary policy bits. */
uint8_t ruleId; /*!< Identifies the Rule for this Flow. */
bool enable;
};
enum class MACsecValidateFrameType : uint8_t
{
Disabled = 0, /*!< Disable validation */
Check = 1, /*!< Enable validation, do not discard invalid frames*/
Strict = 2, /*!< Enable validation and discard invalid frames */
NA = 3 /*!< No processing or accounting */
};
enum class MACsecSecTagIcvStripType : uint8_t
{
StripBoth = 0, /*!< Strip both SecTag and ICV from packet */
StripSecTagPreserveICV = 1,
PreserveSecTagStripICV = 2, /*!< Preserve SecTag, Strip ICV */
PreserveBoth = 3 /*!< Preserve both SecTag and ICV */
};
enum class MACsecCipherSuiteType : uint8_t
{
GcmAes128 = 0,
GcmAes256 = 1,
GcmAes128Xpn = 2,
GcmAes256Xpn = 3
};
struct MACsecSecY
{
uint8_t index; /*!< Identifies the SecY for this Flow. */
bool controlledPortEnabled; /*!< Enable (or disable) operation of the Controlled port associated with this SecY */
MACsecValidateFrameType frameValidationType; /*!< see MACSEC_VALIDATEFRAME */
MACsecSecTagIcvStripType secTagIcvStripType; /*!< see MACSEC_STRIP_SECTAG_ICV */
MACsecCipherSuiteType cipher; /*!< Define the cipher suite to use for this SecY see MACSEC_CIPHER_SUITE */
uint8_t confidentialOffset; /*!< Define the number of bytes that are unencrypted following the SecTag. */
bool icvIncludesDaSa; /*!< When set, the outer DA/SA bytes are included in the authentication GHASH calculation */
bool replayProtect; /*!< Enables Anti-Replay protection */
uint32_t replayWindow; /*!< Unsigned value indicating the size of the anti-replay window. */
bool protectFrames; /*!< 0 = do not encrypt or authenticate this packet; 1 = always Authenticate frame and if SecTag.TCI.E = 1 encrypt the packet as well. */
uint8_t secTagOffset; /*!< Define the offset in bytes from either the start of the packet or a matching Etype depending on SecTag_Insertion_Mode. */
uint8_t secTagTci; /*!< Tag Control Information excluding the AN field which originates from the SA Policy table */
uint16_t mtu; /*!< Specifies the outgoing MTU for this SecY */
bool enable;
};
struct MACsecSc
{
uint8_t index; /*!< SC index. */
uint8_t secYIndex; /*!< SecY associated with this packet. */
uint64_t sci; /*!< The Secure Channel Identifier. */
uint8_t saIndex0; /*!< Define the 1st SA to use */
uint8_t saIndex1; /*!< Define the 2nd SA to use */
bool saIndex0InUse; /*!< Specifies whether 1st SA is in use or not. */
bool saIndex1InUse; /*!< Specifies whether 2nd SA is in use or not. */
bool enableAutoRekey; /*!< If enabled, then once the pn_threshold is reached, auto rekey will happen. */
bool isActiveSa1; /*!< If set, then sa_index1 is the currently active SA index. If cleared, the sa_index0 is the currently active SA index). */
bool enable;
};
struct MACsecSa
{
uint8_t index; /*!< SA index */
std::array<uint8_t, 32> sak; /*!< 256b SAK: Define the encryption key to be used to encrypte this packet. The lower 128 bits are used for 128-bit ciphers. */
std::array<uint8_t, 16> hashKey; /*!< 128b Hash Key: Key used for authentication. */
std::array<uint8_t, 12> salt; /*!< 96b Salt value: Salt value used in XPN ciphers. */
uint32_t ssci; /*!< 32b SSCI value: Short Secure Channel Identifier, used in XPN ciphers. */
uint8_t an; /*!< 2b SecTag Association Number (AN) */
uint64_t nextPn; /*!< 64b next_pn value: Next packet number to insert into outgoing packet on a particular SA. */
bool enable;
};
struct MACSecFlags
{
bool en; // '1' = enable; '0' = disable
};
/* MACSec Settings for 1 port/phy */
struct MACsecConfig
{
static constexpr int NumFlags = 1;
static constexpr int NumRules = 2;
static constexpr int NumMaps = 2;
static constexpr int NumSecY = 2;
static constexpr int NumSc = 2;
static constexpr int NumSa = 4;
MACSecFlags flags;
std::array<MACsecRule, NumRules> rule;
std::array<MACsecMap, NumMaps> map;
std::array<MACsecSecY, NumSecY> secy;
std::array<MACsecSc, NumSc> sc;
std::array<MACsecSa, NumSa> sa;
};
struct MACSecGlobalFlags
{
bool en; // '1' = enable; '0' = disable
bool nvm; // store macsec config in non-volatile memory
};
class MACsecMessage : public Message
{
public:
MACsecMessage(void) : Message(Message::Type::RawMessage) {}
MACSecGlobalFlags flags;
MACsecConfig rx;
MACsecConfig tx;
static std::shared_ptr<MACsecMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
bool EncodeFromMessage(std::vector<uint8_t>& bytestream, const device_eventhandler_t& report) const;
};
}
#endif // __cplusplus
#endif
+1 -1
View File
@@ -4,7 +4,7 @@
#ifdef __cplusplus
#include "icsneo/communication/packet.h"
#include "icsneo/communication/ringbuffer.h"
#include "icsneo/core/ringbuffer.h"
#include "icsneo/api/eventmanager.h"
#include <queue>
#include <vector>
-75
View File
@@ -1,75 +0,0 @@
#ifndef _RINGBUFFER_H_
#define _RINGBUFFER_H_
#include <cstdint>
#include <cstddef>
#include <memory>
#include <cstring>
#include <mutex>
#include <atomic>
#include <vector>
#if __cplusplus >= 202002L
#include <bit>
#endif
namespace icsneo {
class RingBuffer
{
private:
static constexpr size_t RoundUp(size_t size) {
if (size == 0) {
// Avoid underflow when decrementing later
return 1;
} else if (size >= SIZE_MAX) {
// overflow case - resolve to max size
return MaxSize;
}
#if __cplusplus >= 202002L
// c++20 gives us countl_zero which should be more effecient on most platforms
auto lzero = std::countl_zero(size - 1);
auto shift = (sizeof(size_t) * 8) - lzero;
return 1ull << shift;
#else
// Bit twiddling magic! See http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--size;
size |= size >> 1;
size |= size >> 2;
size |= size >> 4;
for (size_t i = 1; i < sizeof(size_t); i <<= 1) {
size |= size >> (i << 3);
}
++size;
return size;
#endif
}
//static_assert(std::atomic<size_t>::is_always_lock_free, "RingBuffer cursor types are not lock-free");
std::atomic<size_t> readCursor;
std::atomic<size_t> writeCursor;
// Use this to mask the cursor values to the buffer size. This is set to capacity - 1 where capacity is always an integral power of 2 (2, 4, 8, 16, etc)
size_t mask;
uint8_t* buf;
public:
static constexpr auto MaxSize = 1ull << ((8 * sizeof(size_t)) - 1);
RingBuffer(size_t bufferSize);
~RingBuffer();
const uint8_t& operator[](size_t offset) const;
size_t size() const;
void pop_front();
void pop(size_t count);
const uint8_t& get(size_t offset) const;
bool write(const uint8_t* addr, size_t count);
bool write(const std::vector<uint8_t>& source);
bool read(uint8_t* dest, size_t startIndex, size_t length) const;
void clear();
constexpr size_t capacity() const {
return mask + 1;
}
protected:
inline uint8_t* resolve(size_t cursor, size_t offset) const {
return &buf[(cursor + offset) & mask];
}
};
}
#endif
@@ -5,13 +5,12 @@
* Author: BJones
*/
#pragma once
#ifndef CRC32_H_
#define CRC32_H_
#ifndef __CRC32_H_
#define __CRC32_H_
#include <stdint.h>
namespace icsneo {
/*
* When any data/buffer is run through calCRC(), then the resulting CRC value
* is appended to the end of the data/buffer and the data/buffer is rerun
@@ -24,4 +23,6 @@
uint32_t crc32(uint32_t crc, const unsigned char* buf, uint32_t len);
uint32_t revcrc32(uint32_t crc, const unsigned char* buf, uint32_t len);
}
#endif // CRC32_H_
+217
View File
@@ -0,0 +1,217 @@
#ifndef __MACSEC_CONFIG_H_
#define __MACSEC_CONFIG_H_
#include <vector>
#include <array>
#include <stdint.h>
#include "icsneo/device/devicetype.h"
namespace icsneo {
struct MACsecVLANTag {
uint16_t vid = 0xFFFFu; /*!< 12 bits */
uint8_t priCfi = 0xFFu; /*!< PRI - 3 bits, CFI - 1bit */
};
struct MACsecMPLSOuter {
uint32_t mplsLabel = 0xFFFFFFFFu; /*!< 20 bits */
uint8_t exp = 0xFFu; /*!< 3 bits */
};
enum class MACsecPacketType : uint8_t {
Default = 0,
SingleVLAN = 1,
DualVLAN = 2,
MPLS = 3,
SingleVLANFollowedByMPLS = 4,
DualVLANFollowedByMPLS = 5,
Unsupported = 6,
};
// Tell the MACsec phy which packets to accept
struct MACsecRxRule {
std::array<uint8_t, 6> keyMacDa = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu}; /*!< MAC DA field extracted from the packet */
std::array<uint8_t, 6> maskMacDa = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu}; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
std::array<uint8_t, 6> keyMacSa = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu}; /*!< MAC SA field extracted from the packet */
std::array<uint8_t, 6> maskMacSa = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu}; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t keyEthertype = 0xFFFFu; /*!< First E-Type found in the packet that doesn't match one of the preconfigured custom tag. */
uint16_t maskEthertype = 0xFFFFu; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecVLANTag keyVlanTagOuter1; /*!< outermost/1st VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
MACsecMPLSOuter keyMplsOuter1;
MACsecVLANTag maskVlanTagOuter1; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecMPLSOuter maskMplsOuter1;
MACsecVLANTag keyVlanTagOuter2; /*!< 2nd outermost VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
MACsecMPLSOuter keyMplsOuter2;
MACsecVLANTag maskVlanTagOuter2; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecMPLSOuter maskMplsOuter2;
uint16_t keyBonusData = 0xFFFFu; /*!< 2 bytes of additional bonus data extracted from one of the custom tags. */
uint16_t maskBonusData = 0xFFFFu; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t keyTagMatchBitmap = 0xFFu; /*!< 8 bits total. Maps 1 to 1 bitwise with the set of custom tags. (set bit[N]=1 if check Nth custom tag) */
uint8_t maskTagMatchBitmap = 0xFFu; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecPacketType keyPacketType = MACsecPacketType::Default; /*!< Encoded Packet Type, see MACSEC_PACKET_TYPE */
uint8_t maskPacketType = 0xFFu; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t keyInnerVlanType = 0xFFFFu; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the second outermost VLAN Tag. */
uint16_t maskInnerVlanType = 0xFFFFu; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t keyOuterVlanType = 0xFFFFu; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the outermost VLAN Tag. */
uint16_t maskOuterVlanType = 0xFFFFu; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t keyNumTags = 0xFFu; /*!< 7 bits total. Number of VLAN/custom tags or MPLS lables detected. Ingress: before SecTag; Egress: total detected. Exclude MCS header tags. i.e. Bit 2: 2 tags/labels before SecTAG...Bit 6: 6 or more tags/labels before SecTAG. */
uint8_t maskNumTags = 0xFFu; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
bool keyExpress = true; /*!< 1 bits. Express packet. */
bool maskExpress = true; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
bool isMpls = false;
};
enum class MACsecValidation : uint8_t {
Disabled = 0, /*!< Disable validation */
Check = 1, /*!< Enable validation, do not discard invalid frames*/
Strict = 2, /*!< Enable validation and discard invalid frames */
NA = 3 /*!< No processing or accounting */
};
enum class MACsecStrip : uint8_t {
StripSecTagAndIcv = 0, /*!< Strip both SecTag and ICV from packet */
StripSecTagPreserveICV = 1,
PreserveSecTagStripICV = 2, /*!< Preserve SecTag, Strip ICV */
NoStrip = 3 /*!< Preserve both SecTag and ICV */
};
enum class MACsecCipherSuite : uint8_t {
GcmAes128 = 0,
GcmAes256 = 1,
GcmAes128Xpn = 2,
GcmAes256Xpn = 3
};
// Tag control information
struct MACsecTci {
bool es = false; // End station bit
bool sc = true; // SCI included bit
bool scb = false; // Single Copy Broadcast
bool e = false; // Encryption bit
bool c = false; // Changed text bit
};
struct MACsecRxSecY {
bool enableControlPort = true; /*!< Enable (or disable) operation of the Controlled port associated with this SecY */
MACsecValidation frameValidation = MACsecValidation::Strict; /*!< see MACSEC_VALIDATEFRAME */
MACsecStrip frameStrip = MACsecStrip::NoStrip; /*!< see MACSEC_STRIP_SECTAG_ICV */
MACsecCipherSuite cipher = MACsecCipherSuite::GcmAes128; /*!< Define the cipher suite to use for this SecY see MACSEC_CIPHER_SUITE */
uint8_t confidentialityOffset = 0; /*!< Define the number of bytes that are unencrypted following the SecTag. */
bool icvIncludesDaSa = true; /*!< When set, the outer DA/SA bytes are included in the authentication GHASH calculation */
bool replayProtect = true; /*!< Enables Anti-Replay protection */
uint32_t replayWindow = 1; /*!< Unsigned value indicating the size of the anti-replay window. */
bool isControlPacket = false; /*!< Identifies all packets matching this index lookup as control packets. */
uint64_t sci; /** The SCI of this secY */
};
struct MACsecTxSecY {
bool enableControlPort = true; /*!< Enable (or disable) operation of the Controlled port associated with this SecY */
MACsecCipherSuite cipher = MACsecCipherSuite::GcmAes128; /*!< Define the cipher suite to use for this SecY see MACSEC_CIPHER_SUITE */
uint8_t confidentialityOffset = 0; /*!< Define the number of bytes that are unencrypted following the SecTag. */
bool icvIncludesDaSa = true; /*!< When set, the outer DA/SA bytes are included in the authentication GHASH calculation */
bool protectFrames = true; /*!< 0 = do not encrypt or authenticate this packet; 1 = always Authenticate frame and if SecTag.TCI.E = 1 encrypt the packet as well. */
uint8_t secTagOffset = 12; /*!< Define the offset in bytes from either the start of the packet or a matching Etype depending on SecTag_Insertion_Mode. */
MACsecTci tci; /*!< Tag Control Information excluding the AN field which originates from the SA Policy table */
uint16_t mtu = 0xFFFFu; /*!< Specifies the outgoing MTU for this SecY */
bool isControlPacket = false; /*!< Identifies all packets matching this index lookup as control packets. */
uint8_t auxiliaryPolicy = 0u; /*!< Auxiliary policy bits. */
uint64_t sci = 0x1122334455660001u;
};
struct MACsecTxSa {
std::array<uint8_t, 32> sak = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}; /*!< 256b SAK: Define the encryption key to be used to encrypte this packet. The lower 128 bits are used for 128-bit ciphers. */
std::array<uint8_t, 16> hashKey = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}; /*!< 128b Hash Key: Key used for authentication. */
std::array<uint8_t, 12> salt = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}; /*!< 96b Salt value: Salt value used in XPN ciphers. */
uint32_t ssci = 0x01u; /*!< 32b SSCI value: Short Secure Channel Identifier, used in XPN ciphers. */
uint8_t an = 0x00;; /*!< 2b SecTag Association Number (AN) */
uint64_t nextPn = 0x01u; /*!< 64b next_pn value: Next packet number to insert into outgoing packet on a particular SA. */
};
struct MACsecRxSa {
std::array<uint8_t, 32> sak = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}; /*!< 256b SAK: Define the encryption key to be used to encrypte this packet. The lower 128 bits are used for 128-bit ciphers. */
std::array<uint8_t, 16> hashKey = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}; /*!< 128b Hash Key: Key used for authentication. */
std::array<uint8_t, 12> salt = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}; /*!< 96b Salt value: Salt value used in XPN ciphers. */
uint32_t ssci = 0x01u; /*!< 32b SSCI value: Short Secure Channel Identifier, used in XPN ciphers. */
uint64_t nextPn = 0x01u; /*!< 64b next_pn value: Next packet number to insert into outgoing packet on a particular SA. */
};
class MACsecConfig {
private:
bool enableRx = false;
bool enableTx = false;
bool nvm = false;
uint8_t maxSecY;
uint8_t maxSa;
uint8_t maxRule;
uint16_t binIndex;
DeviceType type;
std::vector<MACsecRxRule> rxRule;
std::vector<MACsecRxSecY> rxSecY;
std::vector<MACsecTxSecY> txSecY;
std::vector<MACsecTxSa> txSa;
std::vector<MACsecRxSa> rxSa;
std::vector<std::pair<uint8_t, uint8_t>> txSecYSaIndices;
std::vector<std::pair<uint8_t, uint8_t>> rxSecYSaIndices;
std::vector<bool> rxSecYRekey;
std::vector<bool> txSecYRekey;
std::vector<uint8_t> rxRuleIndices;
public:
MACsecConfig() = delete;
MACsecConfig(const DeviceType& deviceType);
int addRxSecY(const MACsecRxSecY& secY, uint8_t saIndex);
int addTxSecY(const MACsecTxSecY& secY, uint8_t saIndex);
int addRxRule(const MACsecRxRule& rule, uint8_t secYIndex);
int addRxSa(const MACsecRxSa& sa);
int addTxSa(const MACsecTxSa& sa);
MACsecRxSecY& getRxSecY(uint8_t secYIndex);
const MACsecRxSecY& getRxSecY(uint8_t secYIndex) const;
MACsecTxSecY& getTxSecY(uint8_t secYIndex);
const MACsecTxSecY& getTxSecY(uint8_t secYIndex) const;
MACsecRxSa& getRxSa(uint8_t saIndex);
const MACsecRxSa& getRxSa(uint8_t saIndex) const;
MACsecTxSa& getTxSa(uint8_t saIndex);
const MACsecTxSa& getTxSa(uint8_t saIndex) const;
MACsecRxRule& getRxRule(uint8_t ruleIndex);
const MACsecRxRule& getRxRule(uint8_t ruleIndex) const;
bool setTxSaIndex(uint8_t secYIndex, uint8_t saIndex);
bool enableTxRekey(uint8_t secYIndex, uint8_t rekeySaIndex);
bool setTxSaRekeyIndex(uint8_t secYIndex, uint8_t saIndex);
void disableTxRekey(uint8_t secYIndex);
bool setRxSaIndex(uint8_t secYIndex, uint8_t saIndex);
bool enableRxRekey(uint8_t secYIndex, uint8_t rekeySaIndex);
bool setRxSaRekeyIndex(uint8_t secYIndex, uint8_t saIndex);
void disableRxRekey(uint8_t secYIndex);
void setRxEnable(bool rxEnable);
void setTxEnable(bool txEnable);
void setStorage(bool temporary);
void clear();
std::vector<uint8_t> serialize() const;
operator bool() const;
uint16_t getBinIndex() const;
DeviceType getType() const;
uint8_t getMaxNumRule() const;
uint8_t getMaxNumSecY() const;
uint8_t getMaxNumSa() const;
};
}
#endif
+75
View File
@@ -0,0 +1,75 @@
#ifndef _RINGBUFFER_H_
#define _RINGBUFFER_H_
#include <cstdint>
#include <cstddef>
#include <memory>
#include <cstring>
#include <mutex>
#include <atomic>
#include <vector>
#if __cplusplus >= 202002L
#include <bit>
#endif
namespace icsneo {
class RingBuffer
{
private:
static constexpr size_t RoundUp(size_t size) {
if (size == 0) {
// Avoid underflow when decrementing later
return 1;
} else if (size >= SIZE_MAX) {
// overflow case - resolve to max size
return MaxSize;
}
#if __cplusplus >= 202002L
// c++20 gives us countl_zero which should be more effecient on most platforms
auto lzero = std::countl_zero(size - 1);
auto shift = (sizeof(size_t) * 8) - lzero;
return 1ull << shift;
#else
// Bit twiddling magic! See http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--size;
size |= size >> 1;
size |= size >> 2;
size |= size >> 4;
for (size_t i = 1; i < sizeof(size_t); i <<= 1) {
size |= size >> (i << 3);
}
++size;
return size;
#endif
}
//static_assert(std::atomic<size_t>::is_always_lock_free, "RingBuffer cursor types are not lock-free");
std::atomic<size_t> readCursor;
std::atomic<size_t> writeCursor;
// Use this to mask the cursor values to the buffer size. This is set to capacity - 1 where capacity is always an integral power of 2 (2, 4, 8, 16, etc)
size_t mask;
uint8_t* buf;
public:
static constexpr auto MaxSize = 1ull << ((8 * sizeof(size_t)) - 1);
RingBuffer(size_t bufferSize);
~RingBuffer();
const uint8_t& operator[](size_t offset) const;
size_t size() const;
void pop_front();
void pop(size_t count);
const uint8_t& get(size_t offset) const;
bool write(const uint8_t* addr, size_t count);
bool write(const std::vector<uint8_t>& source);
bool read(uint8_t* dest, size_t startIndex, size_t length) const;
void clear();
constexpr size_t capacity() const {
return mask + 1;
}
protected:
inline uint8_t* resolve(size_t cursor, size_t offset) const {
return &buf[(cursor + offset) & mask];
}
};
}
#endif
+2 -2
View File
@@ -46,7 +46,7 @@
#include "icsneo/communication/message/extendeddatamessage.h"
#include "icsneo/communication/message/livedatamessage.h"
#include "icsneo/communication/message/tc10statusmessage.h"
#include "icsneo/communication/message/macsecmessage.h"
#include "icsneo/core/macseccfg.h"
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
#include "icsneo/communication/packet/livedatapacket.h"
#include "icsneo/device/extensions/flexray/controller.h"
@@ -855,7 +855,7 @@ public:
std::optional<GPTPStatus> getGPTPStatus(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
/* MACsec support */
virtual bool writeMACsecConfig(const MACsecMessage& message, uint16_t binaryIndex);
virtual bool writeMACsecConfig(const MACsecConfig& cfg);
std::shared_ptr<DeviceExtension> getExtension(const std::string& name) const;