Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EasyConnect Seperation of Concerns Refactor #204

Merged
merged 5 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 99 additions & 26 deletions inc/ec_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,33 +196,97 @@ typedef enum {
ec_session_type_recfg,
} ec_session_type_t;

/**
* @brief The consistent parameters used for all connections between a Configurator and all Enrollees/Agents
*/
typedef struct {
const EC_GROUP *group;
const EVP_MD *hashfcn;
BIGNUM *x, *y, *prime;
BIGNUM *m, *n, *l;
EC_POINT *M, *N;
BN_CTX *bnctx;
EC_KEY *initiator_proto_key;
EC_KEY *responder_proto_key;
EC_POINT *responder_proto_pt;
EC_POINT *responder_connector;
int group_num;
int digestlen;
int noncelen;
const EVP_MD *hash_fcn;
BIGNUM *prime;
BN_CTX *bn_ctx;
int digest_len;
int nonce_len;
int nid;
bool mutual;
unsigned char initiator_keyhash[SHA512_DIGEST_LENGTH];
unsigned char responder_keyhash[SHA512_DIGEST_LENGTH];
unsigned char initiator_nonce[SHA512_DIGEST_LENGTH/2];
unsigned char responder_nonce[SHA512_DIGEST_LENGTH/2];


} ec_persistent_context_t;

/**
* @brief The parameters used only during the creation of a connection between a Configurator and a specific Enrollee/Agent
*/
typedef struct {

/**
* Initiator, Responder, Enrollee, and Configurator Nonces.
* Multiple nonces need to be accounted for at one time.
* These are heap allocated but freed after the auth/cfg process is complete.
*/
uint8_t *i_nonce, *r_nonce, *e_nonce, *c_nonce;

/**
* The protocol key pairs for the initiator and responder. These are are exchanged/generated during the auth/cfg process.
* This must be freed after the auth/cfg process is complete.
*/
EC_POINT *public_init_proto_key, *public_resp_proto_key;
BIGNUM *priv_init_proto_key, *priv_resp_proto_key;

/**
* The generated intermediate keys. These are used multiple times during the auth/cfg process.
* These are heap allocated but freed after the auth/cfg process is complete.
*/
uint8_t *k1, *k2, *ke, *bk;

/**
* The EC x coordinate values for the M, N, and (optional) L points.
* Once generated, these are used multiple times during the auth/cfg process.
*/
BIGNUM *m, *n, *l;

/**
* A random point on the curve for reconfiguration. The same point is used throughout reconfiguration.
* Used from the configurator/controller end as short term memory of which enrollee's it's seen before.
* Used by the enrollee to provide that short term memory to the controller.
* This must be freed after the reconfiguration process is complete.
*/
EC_POINT *E_Id;

uint8_t transaction_id;

/**
* Only needs to be known during the auth process to decide wether or not to generate the L key.
*/
bool is_mutual_auth;

} ec_ephemeral_context_t;

/**
* @brief The parameters used for a specific connection between a Configurator and a specific Enrollee/Agent
*/
typedef struct {
/*
The protocol key of the Enrollee is used as Network Access key (netAccessKey) later in the DPP Configuration and DPP Introduction protocol
*/
EC_KEY *net_access_key;

/* TODO:
Add (if needed):
- C-connector
- c-sign-key
- privacy-protection-key (ppk)

*/

ec_ephemeral_context_t eph_ctx;
} ec_connection_context_t;



/*
REMOVED:
-k1, k2, ke. These are only generated once per device per authentication session (and it should be that way)
unsigned char responder_nonce[SHA512_DIGEST_LENGTH/2];
unsigned char enrollee_nonce[SHA512_DIGEST_LENGTH/2];
unsigned char k1[SHA512_DIGEST_LENGTH];
unsigned char k2[SHA512_DIGEST_LENGTH];
unsigned char ke[SHA512_DIGEST_LENGTH];
unsigned char rauth[SHA512_DIGEST_LENGTH];
unsigned char iauth[SHA512_DIGEST_LENGTH];
} ec_params_t;
*/

typedef struct {

Expand All @@ -232,9 +296,18 @@ typedef struct {
mac_address_t mac_addr;
ec_session_type_t type;

// Updated data
EC_KEY *initiator_boot_key;
EC_KEY *responder_boot_key;
/*
Initiator/Configurator bootstrapping key. (ALWAYS REQUIRED on controller, OPTIONAL on enrollee)
- If this is the Controller, then this key is stored on the Controller.
- If this is the Enrollee, then this key is required for "mutual authentication" and must be recieved via an out-of-band mechanism from the controller.
*/
const EC_KEY *initiator_boot_key;
/*
Responder/Enrollee bootstrapping key. (REQUIRED)
- If this is the Controller, then this key was recieved out-of-band from the Enrollee in the DPP URI
- If this is the Enrollee, then this key is stored locally.
*/
const EC_KEY *responder_boot_key;
} ec_data_t;

#ifdef __cplusplus
Expand Down
179 changes: 179 additions & 0 deletions inc/ec_configurator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#ifndef EC_CONFIGURATOR_H
#define EC_CONFIGURATOR_H

#include <functional>
#include <map>
#include <string>

#include "em_base.h"
#include "ec_crypto.h"


/**
* @brief Sends a chirp notification
*
* @param chirp_tlv The chirp TLV to send
* @param len The length of the chirp TLV
* @return bool true if successful, false otherwise
*/
using send_chirp_func = std::function<bool(em_dpp_chirp_value_t*, size_t)>;

/**
* @brief Sends a proxied encapsulated DPP message
*
* @param encap_dpp_tlv The 1905 Encap DPP TLV to include in the message
* @param encap_dpp_len The length of the 1905 Encap DPP TLV
* @param chirp_tlv The chirp value to include in the message. If NULL, the message will not include a chirp value
* @param chirp_len The length of the chirp value
* @return bool true if successful, false otherwise
*/
using send_encap_dpp_func = std::function<bool(em_encap_dpp_t*, size_t, em_dpp_chirp_value_t*, size_t)>;

/**
* @brief Set the CCE IEs in the beacon and probe response frames
*
* @param bool Whether to enable or disable the inclusion of CCE IEs in the beacon and probe response frames
* @return bool true if successful, false otherwise
*/
using toggle_cce_func = std::function<bool(bool)>;

class ec_configurator_t {
public:
/**
* @brief Construct an EC configurator
*
* @param send_chirp_notification The function to send a chirp notification
* @param send_prox_encap_dpp_msg The function to send a proxied encapsulated DPP message
*/
// TODO: Add send_action_frame and send_gas_frame functions
ec_configurator_t(std::string mac_addr, send_chirp_func send_chirp_notification, send_encap_dpp_func send_prox_encap_dpp_msg);
~ec_configurator_t(); // Destructor

/**
* @brief Set the CCE IEs in the beacon and probe response frames
*
* @param bool Whether to enable or disable the inclusion of CCE IEs in the beacon and probe response frames
* @return bool true if successful, false otherwise
*/
toggle_cce_func m_toggle_cce;

/**
* @brief Start the EC configurator onboarding
*
* @param ec_data The data to use for onboarding (Parsed DPP URI Data)
* @return bool true if successful, false otherwise
*/
bool start(ec_data_t* ec_data);

/**
* @brief Handles a presence announcement 802.11 frame, performing the necessary actions
*
* @param buff The frame to handle
* @param len The length of the frame
* @return bool true if successful, false otherwise
*
* @note Optional to implement because the controller+configurator does not handle 802.11,
* but the proxy agent + configurator does.
*/
virtual bool handle_presence_announcement(uint8_t *buff, unsigned int len) {
return 0; // Optional to implement
}

/**
* @brief Handles an authentication request 802.11 frame, performing the necessary actions
*
* @param buff The frame to handle
* @param len The length of the frame
* @return bool true if successful, false otherwise
*
* @note Optional to implement because the controller+configurator does not handle 802.11,
* but the proxy agent + configurator does.
*/
virtual bool handle_auth_response(uint8_t *buff, unsigned int len) {
return true; // Optional to implement
}

/**
* @brief Handles an configuration request 802.11+GAS frame, performing the necessary actions
*
* @param buff The frame to handle
* @param len The length of the frame
* @return bool true if successful, false otherwise
*
* @note Optional to implement because the controller+configurator does not handle 802.11,
* but the proxy agent + configurator does.
*/
virtual bool handle_cfg_request(uint8_t *buff, unsigned int len) {
return true; // Optional to implement
}

/**
* @brief Handles an configuration result 802.11+GAS frame, performing the necessary actions
*
* @param buff The frame to handle
* @param len The length of the frame
* @return bool true if successful, false otherwise
*
* @note Optional to implement because the controller+configurator does not handle 802.11,
* but the proxy agent + configurator does.
*/
virtual bool handle_cfg_result(uint8_t *buff, unsigned int len) {
return true; // Optional to implement
}

/**
* @brief Handle a chirp notification msg tlv and direct to the correct place (802.11 or 1905)
*
* @param chirp_tlv The chirp TLV to parse and handle
* @param tlv_len The length of the chirp TLV
* @return bool true if successful, false otherwise
*/
virtual bool process_chirp_notification(em_dpp_chirp_value_t* chirp_tlv, uint16_t tlv_len) = 0;

/**
* @brief Handle a proxied encapsulated DPP message TLVs (including chirp value) and direct to the correct place (802.11 or 1905)
*
* @param encap_tlv The 1905 Encap DPP TLV to parse and handle
* @param encap_tlv_len The length of the 1905 Encap DPP TLV
* @param chirp_tlv The DPP Chirp Value TLV to parse and handle (NULL if not present)
* @param chirp_tlv_len The length of the DPP Chirp Value TLV (0 if not present)
* @return bool true if successful, false otherwise
*/
virtual bool process_proxy_encap_dpp_msg(em_encap_dpp_t *encap_tlv, uint16_t encap_tlv_len, em_dpp_chirp_value_t *chirp_tlv, uint16_t chirp_tlv_len) = 0;

inline std::string get_mac_addr() { return m_mac_addr; };

// Disable copy construction and assignment
// Requires use of references or pointers when working with instances of this class
ec_configurator_t(const ec_configurator_t&) = delete;
ec_configurator_t& operator=(const ec_configurator_t&) = delete;

protected:
ec_persistent_context_t m_p_ctx;

ec_data_t m_boot_data;

send_chirp_func m_send_chirp_notification;

send_encap_dpp_func m_send_prox_encap_dpp_msg;

std::string m_mac_addr;

// The connections to the Enrollees/Agents
std::map<std::string, ec_connection_context_t> m_connections;

inline ec_connection_context_t& get_conn_ctx(const std::string& mac) {
// TODO: Add a check for the connection
return m_connections[mac];
}

inline void clear_conn_eph_ctx(const std::string& mac) {
auto conn = m_connections.find(mac);
if (conn == m_connections.end()) return;
auto &eph_ctx = conn->second.eph_ctx;
ec_crypto::free_ephemeral_context(&eph_ctx, m_p_ctx.nonce_len, m_p_ctx.digest_len);
}

};

#endif // EC_CONFIGURATOR_H
Loading