mirror of https://github.com/ARMmbed/mbed-os.git
Squashed 'features/nanostack/sal-stack-nanostack/' changes from 84a07ce..0345477
0345477 Remove test file eapol_helper_stub from release 2f7767a Merge branch 'release_internal' into release_external fdd6c2d wi-sun address registration fix: 48330ea Disabled TLS platform memory 794e053 Wi-sun config sol message handler update c69a41d Removed ETX unknow neighbour trace. 7a5b2a7 Wi-sun State machine update bfc7843 Enabled non-blocking ECC calculation on TLS server ce36f2c Fix issues found by coverity (#2087) 2c4981b DHCP client fix's 6c00aa2 Correcting timeout handling d04523e Added timer to supplicant to filter EAP-TLS re-transmission bursts 3524877 Fix issues found by coverity (#2082) e5f1627 Increased TLS queue size, corrected EUI-64 read and added traces 67bb748 Codereview cleaning's 9350293 DHCPv6 client server address update. de00ace Reduced EAP-TLS retries to from four to two bff9c6e Previous BR EUI-64 is now used on second authentication attempt a2019f4 RPL target address publish update cea03d6 DHCPc6 client cancel support f562de5 Corrected supplicant EAP-TLS sequence id validation bf36b5a Added traces to EAP-TLS delay and TLS protocol 203fdae Removed RSL check from ETX for testing purpose. c1bfeb6 Added print for debugging why SRH validate check fail. fc429e7 Corrected function parameter check 0aef534 Added support for fourth network key to MAC helper and WS bootstrap d861208 Added validation for ETX Acceleration definitions. cbb4acf Accept do faster ETX caclculation after last ETX probe or unicast traffic. 202e579 Removed debug trace print which may affect crash. 68c3d7b Fix missing RPL Prefix Slaac delete handler. 588c385 Drop only non trusted devices when life is over 60 seconds old. 99e8ce7 Cleaned trace print. 8c57c10 Code clean and Keep time update at 16-bit. 9ff35ab ETX calculate and sampling update. 535c005 Corrected EAPOL key reuse on supplicant bootstrap restart 01058c0 Fix for valid lifetime for slaac based address. (#2071) ed4d0c0 Merge pull request #2067 from ARMmbed/IOTTHD-3413 b3ec1f3 MAC: iotthd-3413 Review updates dce4e25 Merge pull request #2068 from ARMmbed/ws_dhcp_update 06fe62e Fixed static definition. 14a244d Wi-sun BBR, bootsrap and RPL Prefix calback update 669b325 DHCPV6 client update d03187e NEW API for do address decrecation 7864962 Added comment for dhcp client configure at Wi-SUN bootstrap. 890f955 Dio prefix handler fix 9f7bf49 Code style, added missing function stub and function rename fix. 78c4ae9 MAC: Added address and pan id filtering for 802.15.4-2015 0ebd37a Wi-sun DHCPV6, RPL DIO forwarding, dhcpv6 client update 85f9a81 Added generation of SLAAC address on BBR (#2065) 561aefa Created Wi-SUN specific NA handler 30bce91 MAC: Moved MAC filters in data ind callback b961948 MAC: Cleaning data indication callback 318ab48 Merge pull request #2064 from ARMmbed/IOTTHD-3426 1a9be20 MAC unit tests: updated cca prepare test fd5683d FHSS WS: Removed temporary debug traces 6527e05 MAC: Fixed multi csma 1e1f69a modified trickle analyse function for pan configuration b7a8268 Merge pull request #2063 from ARMmbed/fhss_mac_retry_correct a21bede CCA RETRY and and TX reretry clear calculation when FHSS re-send packet at new channel. c7235f8 Merge pull request #2062 from ARMmbed/ns_aro_fix 4489dda Merge pull request #2060 from ARMmbed/IOTTHD-3426_traces b1484d8 Corrected GAK generation flagging db51b73 Configure Thread neighbour and destination cache (#2057) 0306276 FHSS WS: Added temporary debug traces 7d88d7f Enabled Multicast NS to trig NA for wi-sun. 609086d Do not add ack callback for multicast NS. be18109 Fixed missing address re registration. 7d8dab4 IPv6 routing cache configuration update (#2056) f701d39 Corrected PAN ID checking for NVM keys and MAC key remove on discovery 1eda5e3 Enabled mbed TLS to use nsdynmemlib on simulator 42c154d Merge pull request #2054 from ARMmbed/IOTTHD-3374 75cce02 Add bootstrap Down event when re-starting network discovery aab7191 MAC: Use minimum CSMA for Asynch 3d93f64 Merge pull request #2053 from ARMmbed/ws_eapol_bootstrap d29dfa7 Merge pull request #2052 from ARMmbed/IOTTHD-3375 7689c8c FHSS WS: Added maximum drift compensation step 7b55332 PAN Configuration failure fix and enabler 1a798ab FHHS old synch disable 47f65aa Merge pull request #2051 from ARMmbed/IOTTHD-3415 324902d Merge pull request #2048 from ARMmbed/IOTTHD-3388 142a32a Update Trickle expiration c5f5fa7 omit NA messages from NS 5d29046 Merge pull request #2040 from ARMmbed/fix_compiler_warnings 8c0b6db FHSS WS: Fixed drifting TX trig timer 708a7d5 Review corrections 1f63902 Merge pull request #2047 from ARMmbed/eapol_bt e9759e8 Added trigger to authenticator to re-start delayed EAP-TLS 30c538a Modified MLR handling c56fa8d Code style fix f298cd3 Parent synch fix and EAPOL synch fix 02942b0 Merge pull request #2046 from ARMmbed/iotthd-3260 5020291 Wi-sun dicovery trickle update 572861b Merge pull request #2041 from ARMmbed/iotthd-3309 e32d3c1 Merge pull request #2038 from ARMmbed/IOTTHD-3341 a2addf8 EAPOL parent synch update b9e3ee0 FHSS WS: Implemented fhss retry logic 1c25c24 Corrected 4WH and GKH replay counters 45a76e1 Corrected eapol key length 39582e8 Merge pull request #2039 from ARMmbed/iotthd-3352 a428ba7 wi-sun LLC update 5ad1743 EAPOL helper update db2e2cd Fix compiler warnings in MDNS service 924acad Fix armc6 compiler warnings 64e924e Check object before usage (#2036) 2d7e923 Corrected supplicant 4WH timeout after Message 1 6cde07a Merge pull request #2034 from ARMmbed/ws_aro_lifetime_fix 9c97cac Merge pull request #2032 from ARMmbed/ws_enable_multi_csma 80ecfdc WS: Enable checking CCA twice on TX channel 780e521 Fixxed ARO lifetime /60 +1 . now resolution is OK. fe4073b Merge pull request #2030 from ARMmbed/IOTTHD-3340 902fdd8 create multicast forward check for PBBR 420c5be Disabled initial EAPOL-Key retry on GTK lifetime mismatch 25ae74e Merge pull request #2029 from ARMmbed/fhss_compensation_fix 6023d7b WS: change csma periods to 1 to make tests pass b5a71c4 MAC unit tests: Updated CCA prepare test a1f3ceb MAC: Make multi CSMA configurable f4e9a1b Disable fhss compensation at parent selection if fixed channel mode is enabled for broadcast. 2417093 Added limits to number of EAP-TLS and TLS sessions 6845ab8 Corrected EAP-TLS retries and ids and initial EAPOL-Key handling 50961c9 Removed random from EAPOL PAN version increment b862823 Fixed interop findings for DUA handling a91a2b4 Thread discovery response update (#2024) ffd4db2 MAC: Implemented double cca check 4ac7842 Corrected authenticator GTK setting 32af62b Merge pull request #2021 from ARMmbed/fhss_synch_fix 5c81b36 ws FHSS synch fix 9dfe724 Corrected 4WH retries and timeouts b47c583 Added check for MBEDTLS_NIST_KW_C flag to nist KW module 2be2634 Merge pull request #2019 from ARMmbed/fhss_warnings_fix 342ca76 FHSS: Fixed IAR warnings from channel functions 359c7b9 Merge pull request #2017 from ARMmbed/IOTTHD-3065 570123d Merge pull request #2015 from ARMmbed/tls_free 1d7693b Change the re-registration delay (#2016) b33e0c1 FHSS WS: Fixed large broadcast interval issue 9640ec0 Merge pull request #2014 from ARMmbed/IOTTHD-3338 798b513 Corrected TLS library free on failure cases f6d1299 FHSS WS: Fixed compensation when on BC channel 5fa004c address entry removal updated (#2013) a8e3e73 Test mode updates for BBR (#2011) d8cc9b5 Merge pull request #2012 from ARMmbed/dhcp_fix 33cd6bf Typo realay->relay. 90a77aa DHCP relay and Renew update bd12214 DHCP client address request update 74dc531 Merge pull request #1994 from ARMmbed/enable_eapol e921dcd Merge pull request #2007 from ARMmbed/ws_mpl_fix 17e27a4 MTD status check added (#2010) a0e893b Merge pull request #2008 from ARMmbed/IOTTHD-3234 274abdd address registration and coap port updates (#2009) ae91f87 MAC: Increase backoff exponent when retry count grows f871797 Merge pull request #2001 from ARMmbed/iotthd-2949 2b6ddf0 Corrected traces and coverity error b0b804d Corrected security protocol data alignment 439e051 Corrected HMAC calculation 6962f42 Corrected traces ff765cf Changed some hex traces to decimals for readability bc3f4f1 Added session message counter check to supplicant 4WH d963915 Corrected four way handshake Message 2 retry 1bcf070 Enable EAPOL flags 83fc53a Security policy check added. (#2004) 7b7e67c MPL SEED ID compres disable for wi-sun. 345c34f Merge pull request #2003 from ARMmbed/fix_rsl_out 716851d Thread uri updated. (#2005) c4d81f4 WS neigh: Fixed reading RSL out ac266e8 Merge pull request #2006 from ARMmbed/merge_nanostack_v10.1.1_changes_back_to_master aaad726 Merge branch 'release_internal' b4fc3f9 Update README (#2002) 64c5f23 Update Pan information when it heard from Parent. 2b61377 RPL DAO target request Update bba1105 Merge pull request #1999 from ARMmbed/IOTTHD-3246 08dfcfc Merge branch 'release_internal' 4edc186 Extra security policy bits handling (#1995) 5a42e88 Corrected PAE controller stop ac2425c Corrected compiling errors d4fded3 Merge pull request #1996 from ARMmbed/ws_bbr_pan_size da6fd12 Fixed Default small network setup set to follow standard. 90a335b Merge pull request #1982 from ARMmbed/iotthd-3258 df2b98e Merge pull request #1979 from ARMmbed/IOTTHD-3233 2b356e0 Added next GTK set to empty functions 3ece393 Corrected compilation warnings from tracing and UT stubs 13e68c3 Corrected defects ac51ec5 Corrected coverity, compiler and astyle errors 96c5496 Added GTK, PMK, PTK lifecycles and node's access of revocation 8f10a6e Fixed tlv length check. (#1992) f2ba36d MAC unit tests: Missing stub added 1ef8dd6 Added public configuration API for Wi-SUN BBR 16d52fb Merge pull request #1991 from ARMmbed/aro_failure_fix 187ad94 Neighbour remove clear active Nud table if neighbor is at list. 5e89e16 Fix ARO register failure handler: 81cd273 Added an extra byte to security policy. (#1989) cd1afb1 MAC: Fixed aborting active TX when sending Ack b0a3c70 WS/MAC: removed trace causing crash, fixed MAC min BE set 3f0e56c FHSS WS: TX poll improvement to enhance hidden node situations 22cbb02 Merge pull request #1983 from ARMmbed/iothhd-2950 3835702 Address policy update's aba9dd6 Updated new rule to address source select 2ed0f76 Fixed Echo request handle 6e31d0a Fix DHCPv6 relay: f40f518 Added prefence time back to ULA prefix add wi-sun. 0bee3db Changed debug traces to info traces 1c45286 Fixed defects and coding style 553fbb1 Corrected memory error on security protocol finish f47ad87 PAE supplicant and authenticator GTK update procedure b4091c0 Defined WS RPL default configure git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: 03454773bef569096bc177fb92930796a2d18c96pull/10624/head^2
parent
fbef0d8e70
commit
1c29564f65
34
README.md
34
README.md
|
@ -1,17 +1,39 @@
|
|||
ARM IPV6/6LoWPAN stack.
|
||||
ARM Mesh networking stack
|
||||
=======================
|
||||
|
||||
This repository contains the ARM IPv6/6LoWPAN/Thread Stack for mbed OS.
|
||||
This repository contains the ARM mesh networking stack that provides support for the following mesh protocols:
|
||||
|
||||
* 6LoWPAN with Neighbor Discovery (ND) and Mesh Link Establishment (MLE)
|
||||
* Thread
|
||||
* Wi-SUN
|
||||
|
||||
All networking stacks are using IEEE 802.15.4 based radios.
|
||||
|
||||
The full documentation is hosted in [Mbed OS documentation](https://os.mbed.com/docs/mbed-os/latest/reference/mesh-tech.html).
|
||||
|
||||
On mbed OS, mesh networking stacks can be used through [Mbed Mesh API](https://os.mbed.com/docs/mbed-os/latest/apis/mesh-api.html) and [Network Socket API](https://os.mbed.com/docs/mbed-os/v5.11/apis/network-socket.html).
|
||||
|
||||
To see, how the mesh networking stack works, check the example application [mbed-os-example-mesh-minimal](https://github.com/ARMmbed/mbed-os-example-mesh-minimal).
|
||||
|
||||
|
||||
##6LoWPAN with ND and MLE
|
||||
|
||||
This networking stack is using standard 6LoWPAN and uses:
|
||||
|
||||
* Neighbor Discovery Protocol ([RFC4861](https://tools.ietf.org/html/rfc4861)) to locate other devices in the mesh network.
|
||||
* Mesh-Link-Establishment ([draft-kelsey-intarea-mesh-link-establishment-06](https://tools.ietf.org/html/draft-kelsey-intarea-mesh-link-establishment-06)) is used for establishing and configuring secure radio links.
|
||||
|
||||
##Thread
|
||||
Thread is standardized by [Thread group](https://www.threadgroup.org/).
|
||||
|
||||
![](docs/img/thread_certified.png)
|
||||
|
||||
mbed OS is now a Thread Certified Component. Using IPv6 with 6LoWPAN as the foundation, Thread technology provides a low-power, self-healing mesh network designed for the home.
|
||||
|
||||
The documentation is hosted in [here](https://os.mbed.com/docs/v5.6/tutorials/6lowpan-mesh.html).
|
||||
##Wi-SUN
|
||||
Wi-SUN (Smart Utility Networks) specification is standardized by [Wi-SUN Alliance](https://www.wi-sun.org/).
|
||||
|
||||
On mbed OS, usage is through [mbed Mesh API](https://os.mbed.com/docs/v5.6/reference/mesh.html) and [Socket API](https://os.mbed.com/docs/v5.6/reference/network-socket.html).
|
||||
|
||||
To see, how the 6LoWPAN Stack works, check the example application [mbed-os-example-mesh-minimal](https://github.com/ARMmbed/mbed-os-example-mesh-minimal).
|
||||
Mbed OS release 5.12 contains the initial Mbed Wi-SUN FAN implementation. Functionality of the Mbed Wi-SUN network stack will be updated when the Wi-SUN protocol is specified further.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -133,6 +133,16 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
|
|||
*/
|
||||
void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address);
|
||||
|
||||
/**
|
||||
* \brief Get DHCPv6 Relay Agent address pointer.
|
||||
*
|
||||
* \param instance The instance ID of the registered server.
|
||||
*
|
||||
* \return NULL when address is not available
|
||||
* {
|
||||
*/
|
||||
uint8_t *dhcp_service_relay_global_addres_get(uint16_t instance);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Deletes a server instance.
|
||||
|
@ -188,6 +198,15 @@ uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr,
|
|||
*/
|
||||
void dhcp_service_set_retry_timers(uint32_t msg_tr_id, uint16_t timeout_init, uint16_t timeout_max, uint8_t retrans_max);
|
||||
|
||||
/**
|
||||
* \brief Update DHCP service server address to active tx process.
|
||||
*
|
||||
* \param msg_tr_id The message transaction ID.
|
||||
* \param server_address New destination address to server / relay Agent.
|
||||
*
|
||||
*/
|
||||
void dhcp_service_update_server_address(uint32_t msg_tr_id, uint8_t *server_address);
|
||||
|
||||
/**
|
||||
* \brief Stops transactions for a message (retransmissions).
|
||||
*
|
||||
|
|
|
@ -143,13 +143,13 @@ typedef int16_t fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_sta
|
|||
typedef uint32_t fhss_read_timestamp(const fhss_api_t *api);
|
||||
|
||||
/**
|
||||
* @brief Get retransmission period. FHSS uses different retry periods for different destinations.
|
||||
* @brief Get additional retransmission period. FHSS uses different retry periods depending on destination or channel availability.
|
||||
* @param api FHSS instance.
|
||||
* @param destination_address Destination MAC address.
|
||||
* @param phy_mtu PHY MTU size.
|
||||
* @return Retransmission period.
|
||||
* @return Retransmission period in microsecond which should be added to normal backoff period.
|
||||
*/
|
||||
typedef uint16_t fhss_get_retry_period(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu);
|
||||
typedef uint32_t fhss_get_retry_period(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu);
|
||||
|
||||
/**
|
||||
* @brief Write synchronization info to given pointer.
|
||||
|
|
|
@ -264,6 +264,7 @@ typedef enum {
|
|||
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
|
||||
macDefaultKeySource = 0x7c, /*<Default key source*/
|
||||
//NON standard extension
|
||||
macMultiCSMAParameters = 0xfa, /*<Multi CSMA parameters*/
|
||||
macRfConfiguration = 0xfb, /*<RF channel configuration parameters*/
|
||||
macAcceptByPassUnknowDevice = 0xfc, /*< Accept data trough MAC if packet is data can be authenticated by group key nad MIC. Security enforsment point must be handled carefully these packets */
|
||||
macLoadBalancingBeaconTx = 0xfd, /*< Trig Beacon from load balance module periodic */
|
||||
|
@ -499,4 +500,14 @@ typedef struct mlme_poll_conf_s {
|
|||
uint8_t status; /**< Status of Poll operation */
|
||||
} mlme_poll_conf_t;
|
||||
|
||||
/**
|
||||
* @brief struct mlme_multi_csma_ca_param_s Set multi CSMA-CA parameters
|
||||
*
|
||||
* Non standard extension to perform CCA multiple times before transmission
|
||||
*/
|
||||
typedef struct mlme_multi_csma_ca_s {
|
||||
uint8_t number_of_csma_ca_periods; /**< Number of CSMA-CA periods */
|
||||
uint16_t multi_cca_interval; /**< Length of the additional CSMA-CA period(s) in microseconds */
|
||||
} mlme_multi_csma_ca_param_t;
|
||||
|
||||
#endif /* MLME_H_ */
|
||||
|
|
|
@ -51,6 +51,40 @@ int8_t arm_nwk_ipv6_frag_mru(uint16_t frag_mru);
|
|||
*/
|
||||
int8_t arm_nwk_ipv6_max_cache_entries(uint16_t max_entries);
|
||||
|
||||
/**
|
||||
* \brief Configure destination cache.
|
||||
*
|
||||
* Set destination cache maximum entry count, thresholds where amount of entries is kept during operation and lifetime.
|
||||
*
|
||||
* Note: This must be called before arm_nwk_interface_lowpan_init()
|
||||
*
|
||||
* \param max_entries Maximum number of entries allowed in destination cache at any time.
|
||||
* \param short_term_threshold Amount of cache entries kept in memory in short term. Must be less than max_entries.
|
||||
* \param long_term_threshold Amount of entries kept in memory over long period of time. Must be less than short_term_threshold.
|
||||
* \param lifetime Lifetime of cache entry, must be over 120 seconds
|
||||
*
|
||||
* \return 0 Change OK.
|
||||
* \return <0 Change invalid - unable to change the maximum for cache.
|
||||
*/
|
||||
int8_t arm_nwk_ipv6_destination_cache_configure(uint16_t max_entries, uint16_t short_term_threshold, uint16_t long_term_threshold, uint16_t lifetime);
|
||||
|
||||
/**
|
||||
* \brief Configure neighbour cache.
|
||||
*
|
||||
* Set neighbour cache maximum entry count, thresholds where amount of entries is kept during operation and lifetime.
|
||||
*
|
||||
* Note: This must be called before arm_nwk_interface_lowpan_init()
|
||||
*
|
||||
* \param max_entries Maximum number of entries allowed in neighbour cache at any time.
|
||||
* \param short_term_threshold Amount of cache entries kept in memory in short term. Must be less than max_entries.
|
||||
* \param long_term_threshold Amount of entries kept in memory over long period of time. Must be less than short_term_threshold.
|
||||
* \param lifetime Lifetime of cache entry, must be over 120 seconds
|
||||
*
|
||||
* \return 0 Change OK.
|
||||
* \return <0 Change invalid - unable to change the maximum for cache.
|
||||
*/
|
||||
int8_t arm_nwk_ipv6_neighbour_cache_configure(uint16_t max_entries, uint16_t short_term_threshold, uint16_t long_term_threshold, uint16_t lifetime);
|
||||
|
||||
/**
|
||||
* \brief Configure automatic flow label calculation.
|
||||
*
|
||||
|
|
|
@ -241,6 +241,19 @@ int thread_test_version_set(int8_t interface_id, uint8_t version);
|
|||
*/
|
||||
int thread_test_router_selection_jitter_set(int8_t interface_id, uint32_t jitter);
|
||||
|
||||
/**
|
||||
* \brief Set Thread PBBR status response override.
|
||||
*
|
||||
* \param interface_id Network Interface
|
||||
* \param dua_status expected dua response value from PBBR
|
||||
* \param dua_count number of times dua_response is repeated
|
||||
* \param ba_failure_count number of times bba failure is repeated
|
||||
*
|
||||
* \return 0, OK
|
||||
* \return <0 Error
|
||||
*/
|
||||
int thread_test_pbbr_response_override_set(int8_t interface_id, uint8_t dua_status, uint8_t dua_count, uint8_t ba_failure_count);
|
||||
|
||||
/**
|
||||
* \brief Sets the thread MIN_DELAY_TIMER default value.
|
||||
*
|
||||
|
|
|
@ -113,9 +113,9 @@ int ws_test_active_key_set(int8_t interface_id, uint8_t index);
|
|||
* Pairwise Transient Key (PTK) lifetimes.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param gtk_lifetime GTK lifetime in minutes
|
||||
* \param pmk_lifetime PMK lifetime in minutes
|
||||
* \param ptk_lifetime PTK lifetime in minutes
|
||||
* \param gtk_lifetime GTK lifetime in minutes or zero if value is not changed
|
||||
* \param pmk_lifetime PMK lifetime in minutes or zero if value is not changed
|
||||
* \param ptk_lifetime PTK lifetime in minutes or zero if value is not changed
|
||||
*
|
||||
* \return 0 Lifetimes are set
|
||||
* \return <0 Lifetime set has failed
|
||||
|
@ -135,9 +135,10 @@ int ws_test_key_lifetime_set(
|
|||
* maximum mismatch time in minutes.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param revocat_lifetime_reduct GTK Revocation Lifetime Reduction (1 / value * GTK lifetime)
|
||||
* \param new_activation_time GTK New Activation Time (1 / value * GTK lifetime)
|
||||
* \param max_mismatch GTK maximum mismatch in minutes
|
||||
* \param revocat_lifetime_reduct GTK Revocation Lifetime Reduction (1 / value * GTK lifetime) or zero if value is not changed
|
||||
* \param new_activation_time GTK New Activation Time (1 / value * GTK lifetime) or zero if value is not changed
|
||||
* \param new_install_req GTK New Install Required (percent * GTK lifetime) or zero if value is not changed
|
||||
* \param max_mismatch GTK maximum mismatch in minutes or zero if value is not changed
|
||||
*
|
||||
* \return 0 Lifetimes are set
|
||||
* \return <0 Lifetime set has failed.
|
||||
|
@ -146,9 +147,26 @@ int ws_test_gtk_time_settings_set(
|
|||
int8_t interface_id,
|
||||
uint8_t revocat_lifetime_reduct,
|
||||
uint8_t new_activation_time,
|
||||
uint8_t new_install_req,
|
||||
uint32_t max_mismatch
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets Next Group Transient Keys used during GTK life cycle
|
||||
*
|
||||
* Sets next Group Transient Keys (GTKs) used during GTK life cycle. Up to four
|
||||
* GTKs can be set (GTKs from index 0 to 3). When next GTK(s) are set, border
|
||||
* router inserts GTKs from the next GTK list into use during GTK update
|
||||
* procedure.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param gtk GTK array, if GTK is not set, pointer for the index shall be NULL.
|
||||
*
|
||||
* \return 0 GTKs are set
|
||||
* \return <0 GTK set has failed
|
||||
*/
|
||||
int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** PHY_LINK_CCA_PREPARE status definitions */
|
||||
#define PHY_TX_NOT_ALLOWED -1 /**< TX not allowed. Do not continue to CCA process. */
|
||||
#define PHY_TX_ALLOWED 0 /**< TX allowed. Continue to CCA process. */
|
||||
#define PHY_RESTART_CSMA 1 /**< Restart CSMA-CA timer. CSMA-CA period must be calculated using given backoff time (PHY_EXTENSION_SET_CSMA_PARAMETERS) */
|
||||
|
||||
/** Interface states */
|
||||
typedef enum {
|
||||
PHY_INTERFACE_RESET, /**< Reset PHY driver and set to idle. */
|
||||
|
@ -45,9 +50,16 @@ typedef enum {
|
|||
PHY_LINK_TX_SUCCESS, /**< MAC TX complete. MAC will a make decision to enter wait ACK or TX done state. */
|
||||
PHY_LINK_TX_FAIL, /**< Link TX process fail. */
|
||||
PHY_LINK_CCA_FAIL, /**< RF link CCA process fail. */
|
||||
PHY_LINK_CCA_PREPARE, /**< RX Tx timeout prepare operation like channel switch to Tx channel from Receive one If operation fail must return not zero*/
|
||||
PHY_LINK_CCA_OK, /**< RF link CCA process ok. */
|
||||
PHY_LINK_CCA_PREPARE, /**< Prepare for CCA after CSMA-CA: changes to CCA channel and gives permission to TX. See PHY_LINK_CCA_PREPARE status definitions for return values */
|
||||
} phy_link_tx_status_e;
|
||||
|
||||
/** MAC filtering modes. Set corresponding bit to 1 (1 << MAC_FRAME_VERSION_X) in PHY_EXTENSION_FILTERING_SUPPORT request when PHY can handle the filtering of this frame type.
|
||||
* NOTE: Currently MAC supports filtering and Acking only 802.15.4-2015 frames. Any other frame version must be filtered and Acked by PHY with either HW or SW solution. */
|
||||
typedef enum {
|
||||
MAC_FRAME_VERSION_2 = 2 /**< 802.15.4-2015 */
|
||||
} phy_link_filters_e;
|
||||
|
||||
/** Extension types */
|
||||
typedef enum {
|
||||
PHY_EXTENSION_CTRL_PENDING_BIT, /**< Control MAC pending bit for indirect data. */
|
||||
|
@ -64,7 +76,8 @@ typedef enum {
|
|||
PHY_EXTENSION_GET_TIMESTAMP, /**< Read 32-bit constant monotonic time stamp in us */
|
||||
PHY_EXTENSION_SET_CSMA_PARAMETERS, /**< CSMA parameter's are given by phy_csma_params_t structure remember type cast uint8_t pointer to structure type*/
|
||||
PHY_EXTENSION_GET_SYMBOLS_PER_SECOND, /**< Read Symbols per seconds which will help to convert symbol time to real time */
|
||||
PHY_EXTENSION_SET_RF_CONFIGURATION /**< Set RF configuration using phy_rf_channel_parameters_s structure */
|
||||
PHY_EXTENSION_SET_RF_CONFIGURATION, /**< Set RF configuration using phy_rf_channel_parameters_s structure */
|
||||
PHY_EXTENSION_FILTERING_SUPPORT /**< Return filtering modes that can be supported by the PHY driver. See phy_link_filters_e */
|
||||
} phy_extension_type_e;
|
||||
|
||||
/** Address types */
|
||||
|
|
|
@ -83,6 +83,7 @@ typedef struct link_configuration {
|
|||
uint8_t version; /**< current protocol version*/
|
||||
uint16_t rfChannel; /**< current rf channel*/
|
||||
uint8_t securityPolicy; /**< Commission Security Policy*/
|
||||
uint8_t securityPolicyExt; /**< Additional Security Policy byte*/
|
||||
uint64_t timestamp;/**< commissioning data set timestamp. [48 bit timestamp seconds]-[15 bit timestamp ticks]-[U bit] */
|
||||
} link_configuration_s;
|
||||
|
||||
|
|
|
@ -45,6 +45,36 @@
|
|||
*/
|
||||
int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
|
||||
|
||||
/**
|
||||
* Border router configuration options
|
||||
*/
|
||||
#define BBR_ULA_C 0x0001 /**< Static ULA prefix created automatically */
|
||||
#define BBR_GUA_C 0x0002 /**< Routable prefix is learned from the backbone */
|
||||
#define BBR_GUA_ROUTE 0x0004 /**< More specific route is added for GUA prefix */
|
||||
#define BBR_GUA_SLAAC 0x0008 /**< Use SLAAC addressing in routable prefix */
|
||||
#define BBR_GUA_WAIT 0x0010 /**< Wait backbone availability before starting RPL dodag */
|
||||
#define BBR_BB_WAIT 0x0020 /**< Wait backbone availability before starting Wi-SUN network */
|
||||
/**
|
||||
* Configure border router features.
|
||||
*
|
||||
* \param interface_id interface ID of the Wi-SUN network
|
||||
* \param options Options configured to Border router
|
||||
* BBR_ULA_C Configure Mesh local ULA prefix with SLAAC address (default)
|
||||
* BBR_GUA_C Configure GUA/ULA prefix from backbone to RPL (default)
|
||||
* BBR_GUA_ROUTE Add more specific route for GUA (default)
|
||||
* BBR_GUA_SLAAC Use SLAAC address generation in GUA prefix
|
||||
* BBR_GUA_WAIT Start RPL root only when GUA is available
|
||||
* BBR_BB_WAIT Start Wi-SUN network only when backbone is ready
|
||||
*
|
||||
* By default Wi-SUN network is started and is treated as separate interface even if backbone is not available.
|
||||
*
|
||||
* Default route RPL options when backbone is set up. RPL root is always Grounded
|
||||
*
|
||||
* \return 0 on success
|
||||
* \return <0 in case of errors
|
||||
*
|
||||
*/
|
||||
int ws_bbr_configure(int8_t interface_id, uint16_t options);
|
||||
/**
|
||||
* Stop backbone Border router.
|
||||
*
|
||||
|
|
|
@ -339,6 +339,26 @@ int8_t mac_helper_security_default_key_set(protocol_interface_info_entry_t *inte
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_security_default_recv_key_set(protocol_interface_info_entry_t *interface, const uint8_t *key, uint8_t id, uint8_t keyid_mode)
|
||||
{
|
||||
if (id == 0 || keyid_mode > 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mac_helper_keytable_descriptor_set(interface->mac_api, key, id, interface->mac_parameters->mac_default_key_attribute_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_security_auto_request_key_index_set(protocol_interface_info_entry_t *interface, uint8_t id)
|
||||
{
|
||||
if (id == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mac_helper_pib_8bit_set(interface, macAutoRequestKeyIndex, id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int8_t mac_helper_security_pairwisekey_set(protocol_interface_info_entry_t *interface, const uint8_t *key, const uint8_t *mac_64, uint8_t key_attribute)
|
||||
{
|
||||
|
@ -374,6 +394,33 @@ int8_t mac_helper_security_prev_key_set(protocol_interface_info_entry_t *interfa
|
|||
|
||||
}
|
||||
|
||||
int8_t mac_helper_security_key_to_descriptor_set(protocol_interface_info_entry_t *interface, const uint8_t *key, uint8_t id, uint8_t descriptor)
|
||||
{
|
||||
if (id == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mac_helper_keytable_descriptor_set(interface->mac_api, key, id, descriptor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_security_key_descriptor_clear(protocol_interface_info_entry_t *interface, uint8_t descriptor)
|
||||
{
|
||||
if (!interface->mac_api) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mlme_set_t set_req;
|
||||
mlme_key_descriptor_entry_t key_description;
|
||||
memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
|
||||
|
||||
set_req.attr = macKeyTable;
|
||||
set_req.value_pointer = &key_description;
|
||||
set_req.value_size = sizeof(mlme_key_descriptor_entry_t);
|
||||
set_req.attr_index = descriptor;
|
||||
interface->mac_api->mlme_req(interface->mac_api, MLME_SET, &set_req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mac_helper_security_key_swap_next_to_default(protocol_interface_info_entry_t *interface)
|
||||
{
|
||||
|
|
|
@ -67,10 +67,18 @@ uint8_t mac_helper_default_key_index_get(struct protocol_interface_info_entry *i
|
|||
|
||||
int8_t mac_helper_security_default_key_set(struct protocol_interface_info_entry *interface, const uint8_t *key, uint8_t id, uint8_t keyid_mode);
|
||||
|
||||
int8_t mac_helper_security_default_recv_key_set(struct protocol_interface_info_entry *interface, const uint8_t *key, uint8_t id, uint8_t keyid_mode);
|
||||
|
||||
int8_t mac_helper_security_auto_request_key_index_set(struct protocol_interface_info_entry *interface, uint8_t id);
|
||||
|
||||
int8_t mac_helper_security_next_key_set(struct protocol_interface_info_entry *interface, uint8_t *key, uint8_t id, uint8_t keyid_mode);
|
||||
|
||||
int8_t mac_helper_security_prev_key_set(struct protocol_interface_info_entry *interface, uint8_t *key, uint8_t id, uint8_t keyid_mode);
|
||||
|
||||
int8_t mac_helper_security_key_to_descriptor_set(struct protocol_interface_info_entry *interface, const uint8_t *key, uint8_t id, uint8_t descriptor);
|
||||
|
||||
int8_t mac_helper_security_key_descriptor_clear(struct protocol_interface_info_entry *interface, uint8_t descriptor);
|
||||
|
||||
void mac_helper_security_key_swap_next_to_default(struct protocol_interface_info_entry *interface);
|
||||
|
||||
int8_t mac_helper_security_pairwisekey_set(struct protocol_interface_info_entry *interface, const uint8_t *key, const uint8_t *mac_64, uint8_t key_attribute);
|
||||
|
|
|
@ -926,7 +926,7 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin
|
|||
|
||||
/* TODO - check hard upper limit on registrations? */
|
||||
if (ws_info(cur_interface) &&
|
||||
!ws_common_allow_child_registration(cur_interface)) {
|
||||
!ws_common_allow_child_registration(cur_interface, aro_out->eui64)) {
|
||||
aro_out->present = true;
|
||||
aro_out->status = ARO_FULL;
|
||||
return true;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
void thread_address_registration_init(void);
|
||||
bool thread_address_registration_running(void);
|
||||
void thread_address_registration_deinit(void);
|
||||
|
||||
void thread_address_registration_timer_set(protocol_interface_info_entry_t *interface, uint16_t dua_delay_seconds, uint16_t mlr_refresh_seconds);
|
||||
|
@ -41,6 +42,7 @@ void thread_address_registration_timer(protocol_interface_info_entry_t *interfac
|
|||
#else
|
||||
|
||||
#define thread_address_registration_init(void)
|
||||
#define thread_address_registration_running(void)
|
||||
#define thread_address_registration_deinit(void)
|
||||
|
||||
#define thread_address_registration_timer_set(interface, dua_delay_seconds, mlr_refresh_seconds);
|
||||
|
|
|
@ -517,6 +517,34 @@ static int thread_border_relay_to_leader_cb(int8_t service_id, uint8_t source_ad
|
|||
}
|
||||
|
||||
#ifdef HAVE_THREAD_BORDER_ROUTER
|
||||
static bool thread_bbr_default_route_exists(struct protocol_interface_info_entry *cur, uint8_t prefix_ptr[8])
|
||||
{
|
||||
uint16_t rloc16 = mac_helper_mac16_address_get(cur);
|
||||
ns_list_foreach(thread_network_data_prefix_cache_entry_t, prefix, &cur->thread_info->networkDataStorage.localPrefixList) {
|
||||
|
||||
if (prefix_ptr &&
|
||||
(prefix->servicesPrefixLen != 64 ||
|
||||
memcmp(prefix_ptr, prefix->servicesPrefix, 8) != 0)) {
|
||||
// Only matching prefixes are counted
|
||||
continue;
|
||||
}
|
||||
|
||||
ns_list_foreach(thread_network_server_data_entry_t, br, &prefix->borderRouterList) {
|
||||
if (br->routerID == 0xfffe) {
|
||||
continue;
|
||||
}
|
||||
if (!br->P_default_route) {
|
||||
continue;
|
||||
}
|
||||
if (rloc16 != br->routerID) {
|
||||
// different default route exists
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool thread_bbr_i_host_prefix(struct protocol_interface_info_entry *cur, uint8_t prefix_ptr[8], uint8_t *br_count, bool *i_am_lowest)
|
||||
{
|
||||
bool i_host_this_prefix = false;
|
||||
|
@ -600,14 +628,15 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8],
|
|||
this->br_info_published = true;
|
||||
}
|
||||
|
||||
static void thread_bbr_routing_enable(thread_bbr_t *this)
|
||||
static void thread_bbr_routing_enable(thread_bbr_t *this, bool multicast_routing_enabled)
|
||||
{
|
||||
if (this->routing_enabled) {
|
||||
return;
|
||||
}
|
||||
tr_info("br: enable routing");
|
||||
// Start multicast proxying
|
||||
multicast_fwd_set_forwarding(this->interface_id, true);
|
||||
// We do not enable multicast forwarding as there is other default router present in network
|
||||
multicast_fwd_set_forwarding(this->interface_id, multicast_routing_enabled);
|
||||
this->routing_enabled = true;
|
||||
}
|
||||
|
||||
|
@ -663,7 +692,13 @@ static void thread_bbr_status_check(thread_bbr_t *this, uint32_t seconds)
|
|||
|
||||
// Check from network data are we currently BR or not and change routing state
|
||||
if (this->br_hosted) {
|
||||
thread_bbr_routing_enable(this);
|
||||
|
||||
//If there is a default router present in any prefix other than us we do not forward multicast
|
||||
//This prevents multicasts to different interfaces where Thread Mesh is forwarder
|
||||
bool forward_multicast = !thread_bbr_default_route_exists(cur, NULL);
|
||||
thread_extension_bbr_mcast_fwd_check(cur->id, &forward_multicast);
|
||||
|
||||
thread_bbr_routing_enable(this, forward_multicast);
|
||||
} else {
|
||||
thread_bbr_routing_disable(this);
|
||||
}
|
||||
|
@ -896,6 +931,15 @@ int8_t thread_bbr_init(int8_t interface_id, uint16_t external_commisssioner_port
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t thread_bbr_get_commissioner_service(int8_t interface_id)
|
||||
{
|
||||
thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
|
||||
if (!this) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this->br_service_id;
|
||||
}
|
||||
void thread_bbr_delete(int8_t interface_id)
|
||||
{
|
||||
thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
|
||||
|
@ -1100,8 +1144,11 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id)
|
|||
// By default multicast forwarding is not enabled as it causes multicast loops
|
||||
multicast_fwd_set_forwarding(this->interface_id, false);
|
||||
|
||||
// Adjust BBR neighbor and destination cache size
|
||||
arm_nwk_ipv6_max_cache_entries(THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE);
|
||||
// Configure BBR neighbour cache parameters
|
||||
arm_nwk_ipv6_neighbour_cache_configure(THREAD_BBR_IPV6_NEIGHBOUR_CACHE_SIZE,
|
||||
THREAD_BBR_IPV6_NEIGHBOUR_CACHE_SHORT_TERM,
|
||||
THREAD_BBR_IPV6_NEIGHBOUR_CACHE_LONG_TERM,
|
||||
THREAD_BBR_IPV6_NEIGHBOUR_CACHE_LIFETIME);
|
||||
|
||||
thread_extension_bbr_init(interface_id, backbone_interface_id);
|
||||
|
||||
|
@ -1125,6 +1172,7 @@ int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t tim
|
|||
#endif // HAVE_THREAD_BORDER_ROUTER
|
||||
}
|
||||
|
||||
|
||||
int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix)
|
||||
{
|
||||
(void) interface_id;
|
||||
|
@ -1159,8 +1207,6 @@ int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8
|
|||
#endif // HAVE_THREAD_BORDER_ROUTER
|
||||
}
|
||||
|
||||
|
||||
|
||||
void thread_bbr_stop(int8_t interface_id)
|
||||
{
|
||||
(void) interface_id;
|
||||
|
|
|
@ -66,6 +66,13 @@ void thread_bbr_seconds_timer(int8_t interface_id, uint32_t tics);
|
|||
* \param interface_id current interface id
|
||||
*/
|
||||
int thread_bbr_commissioner_proxy_service_update(int8_t interface_id);
|
||||
/**
|
||||
* \brief get commissioner service id to add new services
|
||||
*
|
||||
* \param interface_id current interface id
|
||||
* \return service id or 0 if invalid
|
||||
*/
|
||||
int8_t thread_bbr_get_commissioner_service(int8_t interface_id);
|
||||
|
||||
#else
|
||||
#define thread_bbr_init(interface_id, external_commisssioner_port)
|
||||
|
|
|
@ -888,6 +888,7 @@ void thread_interface_init(protocol_interface_info_entry_t *cur)
|
|||
thread_discovery_reset(cur->id);
|
||||
thread_routing_set_mesh_callbacks(cur);
|
||||
dhcp_client_init(cur->id);
|
||||
dhcp_client_configure(cur->id, false, false, false);
|
||||
thread_management_client_init(cur->id);
|
||||
thread_address_registration_init();
|
||||
cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT;
|
||||
|
@ -945,6 +946,31 @@ static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t
|
|||
tr_debug("Set End node Mode");
|
||||
cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE;
|
||||
}
|
||||
|
||||
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
|
||||
// set router neighbour cache
|
||||
ipv6_neighbour_cache_configure(THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_SIZE,
|
||||
THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_SHORT_TERM,
|
||||
THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_LONG_TERM,
|
||||
THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_LIFETIME);
|
||||
// set router destination cache
|
||||
ipv6_destination_cache_configure(THREAD_ROUTER_IPV6_DESTINATION_CACHE_SIZE,
|
||||
THREAD_ROUTER_IPV6_DESTINATION_CACHE_SHORT_TERM,
|
||||
THREAD_ROUTER_IPV6_DESTINATION_CACHE_LONG_TERM,
|
||||
THREAD_ROUTER_IPV6_DESTINATION_CACHE_LIFETIME);
|
||||
} else {
|
||||
// device is some sort of end device
|
||||
ipv6_neighbour_cache_configure(THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_SIZE,
|
||||
THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_SHORT_TERM,
|
||||
THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_LONG_TERM,
|
||||
THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_LIFETIME);
|
||||
|
||||
ipv6_destination_cache_configure(THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_SIZE,
|
||||
THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_SHORT_TERM,
|
||||
THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_LONG_TERM,
|
||||
THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_LIFETIME);
|
||||
}
|
||||
|
||||
cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
|
||||
}
|
||||
|
||||
|
@ -2540,7 +2566,7 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur,
|
|||
} else {
|
||||
tr_debug("SLAAC address set as NOT preferred.");
|
||||
}
|
||||
addr_set_preferred_lifetime(cur, e, genericService.P_preferred ? 0xfffffffff : 0);
|
||||
addr_set_preferred_lifetime(cur, e, genericService.P_preferred ? 0xffffffff : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -988,11 +988,7 @@ void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
|
|||
thread_resolution_client_timer(cur->id, ticks);
|
||||
thread_key_switch_timer(cur, ticks);
|
||||
thread_child_update_req_timer(cur, ticks);
|
||||
|
||||
if (!thread_bootstrap_should_register_address(cur)) {
|
||||
/* Only FTD refreshes the address registration timer */
|
||||
thread_address_registration_timer(cur, ticks);
|
||||
}
|
||||
|
||||
if (thread_attach_ready(cur) != 0) {
|
||||
return;
|
||||
|
|
|
@ -192,6 +192,7 @@ typedef struct thread_connectivity_s {
|
|||
typedef struct thread_parent_info_s {
|
||||
uint8_t mac64[8];
|
||||
uint16_t shortAddress;
|
||||
uint16_t version;
|
||||
uint8_t router_id;
|
||||
uint8_t pathCostToLeader;
|
||||
bool childUpdatePending: 1;
|
||||
|
|
|
@ -326,11 +326,34 @@
|
|||
*/
|
||||
#define THREAD_BBR_ROUTER_ID_REQUEST_STATUS THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST
|
||||
|
||||
/*
|
||||
* Number of destination and neighbor cache entries assuming 250 thread devices (worst case) connecting to cloud service.
|
||||
/* Border Router IPv6 neighbour and destination cache configuration
|
||||
* Number of neighbor cache entries assuming 250 thread devices (worst case) connecting to cloud service.
|
||||
* Six entries reserved for backbone devices.
|
||||
*/
|
||||
#define THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE 256
|
||||
#define THREAD_BBR_IPV6_NEIGHBOUR_CACHE_SIZE 256
|
||||
#define THREAD_BBR_IPV6_NEIGHBOUR_CACHE_SHORT_TERM 128
|
||||
#define THREAD_BBR_IPV6_NEIGHBOUR_CACHE_LONG_TERM 32
|
||||
#define THREAD_BBR_IPV6_NEIGHBOUR_CACHE_LIFETIME 600
|
||||
|
||||
/* Router IPv6 neighbour and destination cache configuration */
|
||||
#define THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_SIZE 128
|
||||
#define THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_SHORT_TERM 64
|
||||
#define THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_LONG_TERM 8
|
||||
#define THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_LIFETIME 600
|
||||
#define THREAD_ROUTER_IPV6_DESTINATION_CACHE_SIZE 32
|
||||
#define THREAD_ROUTER_IPV6_DESTINATION_CACHE_SHORT_TERM 16
|
||||
#define THREAD_ROUTER_IPV6_DESTINATION_CACHE_LONG_TERM 4
|
||||
#define THREAD_ROUTER_IPV6_DESTINATION_CACHE_LIFETIME 600
|
||||
|
||||
/* End device IPv6 neighbour and destination cache configuration */
|
||||
#define THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_SIZE 32
|
||||
#define THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_SHORT_TERM 16
|
||||
#define THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_LONG_TERM 4
|
||||
#define THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_LIFETIME 600
|
||||
#define THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_SIZE 16
|
||||
#define THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_SHORT_TERM 8
|
||||
#define THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_LONG_TERM 4
|
||||
#define THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_LIFETIME 600
|
||||
|
||||
/*
|
||||
* Timeout to solicit address from DHCP if previous request fails.
|
||||
|
|
|
@ -49,6 +49,7 @@ void thread_extension_mtd_service_register(protocol_interface_info_entry_t *cur)
|
|||
void thread_extension_network_data_process(struct protocol_interface_info_entry *cur);
|
||||
int thread_extension_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *timer1_ptr, uint32_t *timer2_ptr);
|
||||
void thread_extension_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected);
|
||||
void thread_extension_child_address_registration_response_process(struct protocol_interface_info_entry *interface);
|
||||
void thread_extension_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len);
|
||||
void thread_extension_aloc_generate(struct protocol_interface_info_entry *cur);
|
||||
bool thread_extension_aloc_map(protocol_interface_info_entry_t *cur, uint16_t *addr16);
|
||||
|
@ -62,11 +63,13 @@ int thread_extension_service_init(protocol_interface_info_entry_t *cur);
|
|||
void thread_extension_addr_ntf_send(struct protocol_interface_info_entry *cur, uint8_t *destination_address, const uint8_t *addr_data_ptr, uint8_t bbr_status);
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
bool thread_extension_joining_enabled(int8_t interface_id);
|
||||
bool thread_extension_is_reed_upgrade_allowed(protocol_interface_info_entry_t *cur);
|
||||
uint8_t thread_extension_discover_response_len(protocol_interface_info_entry_t *cur);
|
||||
uint8_t *thread_extension_discover_response_write(protocol_interface_info_entry_t *cur, uint8_t *ptr);
|
||||
|
||||
#else
|
||||
#define thread_extension_joining_enabled(interface_id) (false)
|
||||
#define thread_extension_is_reed_upgrade_allowed(cur) (true)
|
||||
#define thread_extension_discover_response_len(cur) (0)
|
||||
#define thread_extension_discover_response_write(cur, ptr) (ptr)
|
||||
#endif //HAVE_THREAD_ROUTER
|
||||
|
@ -78,10 +81,12 @@ uint8_t *thread_extension_discover_response_write(protocol_interface_info_entry_
|
|||
#define thread_extension_network_data_process(cur) ((void) 0)
|
||||
#define thread_extension_primary_bbr_get(cur,addr_ptr,seq_ptr,timer1_ptr, timer2_ptr) (-1)
|
||||
#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) ((void) 0)
|
||||
#define thread_extension_child_address_registration_response_process(interface) ((void) 0)
|
||||
#define thread_extension_aloc_generate(cur) ((void) 0)
|
||||
#define thread_extension_aloc_map(cur, addr16) (false)
|
||||
#define thread_extension_mcast_subscrition_change(interface) ((void) 0)
|
||||
#define thread_extension_enabled(cur) (false)
|
||||
#define thread_extension_is_reed_upgrade_allowed(cur) (true)
|
||||
#define thread_extension_version_check(version) (false)
|
||||
#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) ((void) 0)
|
||||
#define thread_extension_discover_response_tlv_write(data, version, securityPolicy) ((void) 0)
|
||||
|
|
|
@ -47,7 +47,6 @@ typedef struct thread_pbbr_dua_info {
|
|||
} thread_pbbr_dua_info_t;
|
||||
|
||||
#if defined(HAVE_THREAD_V2) && defined(HAVE_THREAD_BORDER_ROUTER)
|
||||
|
||||
int8_t thread_extension_bbr_init(int8_t interface_id, int8_t backbone_interface_id);
|
||||
void thread_extension_bbr_delete(int8_t interface_id);
|
||||
bool thread_extension_bbr_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc);
|
||||
|
@ -58,6 +57,10 @@ int thread_extension_bbr_address_set(int8_t interface_id, const uint8_t *addr_pt
|
|||
void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur);
|
||||
int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix);
|
||||
void thread_extension_bbr_old_partition_data_clean(int8_t interface_id);
|
||||
void thread_extension_bbr_status_override_get(uint8_t *dua_status, uint8_t *dua_count, uint8_t *ba_failure_count);
|
||||
void thread_extension_bbr_status_override_set(uint8_t dua_status, uint8_t dua_count, uint8_t ba_failure_count);
|
||||
void thread_extension_status_override_count_set(uint8_t value);
|
||||
void thread_extension_bbr_mcast_fwd_check(int8_t interface_id, bool *multicast_fwd);
|
||||
|
||||
|
||||
#else
|
||||
|
@ -72,6 +75,10 @@ void thread_extension_bbr_old_partition_data_clean(int8_t interface_id);
|
|||
#define thread_extension_bbr_sequence_number_set(interface_id, seq_number) (-1)
|
||||
#define thread_extension_bbr_prefix_set(interface_id, prefix) 0
|
||||
#define thread_extension_bbr_old_partition_data_clean(interface_id)
|
||||
#define thread_extension_bbr_status_override_get(dua_status, dua_count, ba_failure_count);
|
||||
#define thread_extension_bbr_status_override_set(dua_status, dua_count, ba_failure_count);
|
||||
#define thread_extension_status_override_count_set(value)
|
||||
#define thread_extension_bbr_mcast_fwd_check(interface_id, multicast_fwd)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
|
@ -38,6 +39,7 @@ extern "C" {
|
|||
#define thread_extension_bootstrap_free(cur);
|
||||
#define thread_extension_bootstrap_device_certificate_set(cur, device_certificate_ptr, device_certificate_len, priv_key_ptr, priv_key_len) (-1)
|
||||
#define thread_extension_bootstrap_network_certificate_set(cur, domain_certificate_ptr, domain_certificate_len) (-1)
|
||||
#define thread_extension_bootstrap_network_certificate_available(cur) (false)
|
||||
#define thread_extension_bootstrap_network_private_key_set(cur, priv_key_ptr, priv_key_len) (-1)
|
||||
#define thread_extension_bootstrap_thread_name_set(cur, thread_name) (-1)
|
||||
#define thread_extension_bootstrap_commission_start(cur, parent_address, port, done_cb) (-1)
|
||||
|
|
|
@ -897,6 +897,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message
|
|||
parent->shortAddress = scan_result->shortAddress;
|
||||
parent->router_id = (scan_result->shortAddress >> 10);
|
||||
memcpy(parent->mac64, scan_result->mac64, 8);
|
||||
parent->version = scan_result->version;
|
||||
//Check Network Data TLV
|
||||
if (networkDataTlv.tlvType == MLE_TYPE_NETWORK_DATA) {
|
||||
thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "thread_network_synch.h"
|
||||
#include "thread_network_data_lib.h"
|
||||
#include "thread_joiner_application.h"
|
||||
#include "thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "mac_api.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
|
@ -318,6 +319,7 @@ static link_configuration_s *link_configuration_create(void)
|
|||
}
|
||||
memset(this, 0, sizeof(link_configuration_s));
|
||||
this->securityPolicy = SECURITY_POLICY_ALL_SECURITY; // Set all default values ('1') for security policy flags
|
||||
this->securityPolicyExt = SECURITY_POLICY_ALL_SECURITY; // Set all default values
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -345,6 +347,7 @@ static void link_configuration_copy(link_configuration_s *this, link_configurati
|
|||
this->panId = configuration_ptr->panId;
|
||||
this->rfChannel = configuration_ptr->rfChannel;
|
||||
this->securityPolicy = configuration_ptr->securityPolicy;
|
||||
this->securityPolicyExt = configuration_ptr->securityPolicyExt;
|
||||
this->timestamp = configuration_ptr->timestamp;
|
||||
return;
|
||||
}
|
||||
|
@ -396,10 +399,14 @@ static int link_configuration_update(link_configuration_s *link_configuration, u
|
|||
if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_PSKC, &ptr) >= 16) {
|
||||
memcpy(link_configuration->PSKc, ptr, 16);
|
||||
}
|
||||
|
||||
if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_SECURITY_POLICY, &ptr) >= 3) {
|
||||
uint16_t tlv_len = thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_SECURITY_POLICY, &ptr);
|
||||
if (tlv_len >= 3) {
|
||||
link_configuration->securityPolicyExt = SECURITY_POLICY_ALL_SECURITY;
|
||||
link_configuration->securityPolicy = ptr[2];
|
||||
link_configuration->key_rotation = common_read_16_bit(ptr);
|
||||
if (tlv_len > 3) {
|
||||
link_configuration->securityPolicyExt = ptr[3];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -512,8 +519,8 @@ static void device_configuration_validate(device_configuration_s *this)
|
|||
this->vendor_stack_version[1] = (uint8_t)(THREAD_ARM_OUI >> 8);
|
||||
this->vendor_stack_version[2] = (uint8_t)(THREAD_ARM_OUI);
|
||||
this->vendor_stack_version[3] = (uint8_t)(THREAD_BUILD_NUMBER >> 4);
|
||||
this->vendor_stack_version[4] = (uint8_t)(((THREAD_BUILD_NUMBER & 0x0f) << 4) || THREAD_REVISION_NUMBER);
|
||||
this->vendor_stack_version[5] = (uint8_t)((THREAD_VERSION_MIN << 4) || THREAD_VERSION_MAJ);
|
||||
this->vendor_stack_version[4] = (uint8_t)(((THREAD_BUILD_NUMBER & 0x0f) << 4) | THREAD_REVISION_NUMBER);
|
||||
this->vendor_stack_version[5] = (uint8_t)((THREAD_VERSION_MIN << 4) | THREAD_VERSION_MAJ);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,7 +717,7 @@ static void configuration_set_copy_mandatory(configuration_set_t *destination_pt
|
|||
tr_debug("mandatory TLVs needed: %s", trace_array(tlv_list, tlv_list_len));
|
||||
configuration_set_add_fields(destination_ptr, source_ptr->data, source_ptr->length, tlv_list, tlv_list_len);
|
||||
}
|
||||
static void configuration_set_generate(configuration_set_t *destination_ptr, link_configuration_s *configuration_ptr)
|
||||
static void configuration_set_generate(int8_t interface_id, configuration_set_t *destination_ptr, link_configuration_s *configuration_ptr)
|
||||
{
|
||||
uint8_t *response_ptr;
|
||||
|
||||
|
@ -733,11 +740,18 @@ static void configuration_set_generate(configuration_set_t *destination_ptr, lin
|
|||
response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_PSKC, 16, configuration_ptr->PSKc);
|
||||
response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_NETWORK_NAME, stringlen((char *)&configuration_ptr->name, 16), configuration_ptr->name);
|
||||
*response_ptr++ = MESHCOP_TLV_SECURITY_POLICY; // type
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (thread_extension_version_check(thread_info(cur)->version)) {
|
||||
*response_ptr++ = 4; // length
|
||||
response_ptr = common_write_16_bit(configuration_ptr->key_rotation, response_ptr);
|
||||
*response_ptr++ = configuration_ptr->securityPolicy;
|
||||
*response_ptr++ = configuration_ptr->securityPolicyExt;
|
||||
} else {
|
||||
*response_ptr++ = 3; // length
|
||||
response_ptr = common_write_16_bit(configuration_ptr->key_rotation, response_ptr);
|
||||
*response_ptr++ = configuration_ptr->securityPolicy;
|
||||
}
|
||||
response_ptr = thread_tmfcop_tlv_data_write_uint64(response_ptr, MESHCOP_TLV_ACTIVE_TIME_STAMP, configuration_ptr->timestamp);
|
||||
|
||||
destination_ptr->length = response_ptr - destination_ptr->data;
|
||||
}
|
||||
|
||||
|
@ -859,7 +873,7 @@ int thread_joiner_application_init(int8_t interface_id, device_configuration_s *
|
|||
//If no master key or PSKc set we assume not valid configuration for thread network others may be possible to be 0
|
||||
//This allows some configurations to be set statically for testing purposes
|
||||
this->configuration_valid = true;
|
||||
configuration_set_generate(this->active_configuration_ptr, this->configuration_ptr);
|
||||
configuration_set_generate(this->interface_id, this->active_configuration_ptr, this->configuration_ptr);
|
||||
}
|
||||
}
|
||||
// Always load link configuration from bootstrap state machine. NVM overrides Static configuration
|
||||
|
@ -1533,7 +1547,7 @@ int thread_joiner_application_link_configuration_store(int8_t interface_id, link
|
|||
}
|
||||
|
||||
thread_joiner_application_validate_settings(this);// Generate all random information
|
||||
configuration_set_generate(this->active_configuration_ptr, link_config);
|
||||
configuration_set_generate(this->interface_id, this->active_configuration_ptr, link_config);
|
||||
link_configuration_update(this->configuration_ptr, this->active_configuration_ptr->data, this->active_configuration_ptr->length);
|
||||
this->configuration_ptr->key_sequence = link_config->key_sequence;
|
||||
this->configuration_valid = true;
|
||||
|
|
|
@ -744,6 +744,7 @@ static bool thread_address_registration_tlv_check(protocol_interface_info_entry_
|
|||
}
|
||||
}
|
||||
}
|
||||
thread_extension_child_address_registration_response_process(cur);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
#include "6LoWPAN/Thread/thread_neighbor_class.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "thread_management_if.h"
|
||||
#include "Common_Protocols/ipv6.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
|
@ -1484,6 +1485,12 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
|
|||
return;
|
||||
}
|
||||
|
||||
// check if security policy prevents sending of parent response
|
||||
if (!thread_extension_is_reed_upgrade_allowed(cur)) {
|
||||
tr_debug("Security policy prevents parent response; drop packet");
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread_am_reed(cur)) {
|
||||
// If we are in REED mode and receive PARENT_REQ from our parent, don't send response.
|
||||
if (thread_router_parent_address_check(cur, mle_msg->packet_src_address)) {
|
||||
|
@ -1597,8 +1604,14 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
|
|||
return;
|
||||
}
|
||||
|
||||
// If we are in REED mode and receive child ID request from our parent, call connection error.
|
||||
// check if security policy prevents sending of child id response
|
||||
if (!thread_extension_is_reed_upgrade_allowed(cur)) {
|
||||
tr_debug("Security policy prevents child id response; drop packet");
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread_am_reed(cur)) {
|
||||
// If we are in REED mode and receive child ID request from our parent, call connection error.
|
||||
if (thread_router_parent_address_check(cur, mle_msg->packet_src_address)) {
|
||||
tr_debug("Child ID req from own parent -> connection error");
|
||||
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
|
||||
|
@ -2226,6 +2239,10 @@ bool thread_router_bootstrap_reed_upgrade(protocol_interface_info_entry_t *cur)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!thread_extension_is_reed_upgrade_allowed(cur)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thread_am_router(cur)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "6LoWPAN/Thread/thread_discovery.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bbr.h"
|
||||
#include "6LoWPAN/Thread/thread_neighbor_class.h"
|
||||
#include "MLE/mle.h"
|
||||
#include "thread_meshcop_lib.h"
|
||||
|
@ -639,6 +640,23 @@ int thread_test_version_set(int8_t interface_id, uint8_t version)
|
|||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int thread_test_pbbr_response_override_set(int8_t interface_id, uint8_t dua_status, uint8_t dua_count, uint8_t ba_failure_count)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
(void)interface_id;
|
||||
thread_extension_bbr_status_override_set(dua_status, dua_count, ba_failure_count);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
(void)interface_id;
|
||||
(void)dua_status;
|
||||
(void)dua_count;
|
||||
(void)ba_failure_count;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int thread_test_router_selection_jitter_set(int8_t interface_id, uint32_t jitter)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
|
|
|
@ -35,8 +35,11 @@
|
|||
#include "net_rpl.h"
|
||||
#include "Service_Libs/nd_proxy/nd_proxy.h"
|
||||
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "DHCPv6_Server/DHCPv6_server_service.h"
|
||||
|
||||
#include "ws_bbr_api.h"
|
||||
|
||||
#define TRACE_GROUP "wsbs"
|
||||
|
||||
#define RPL_INSTANCE_ID 1
|
||||
|
@ -49,6 +52,7 @@
|
|||
*
|
||||
*/
|
||||
static int8_t backbone_interface_id = -1; // BBR backbone information
|
||||
static uint16_t configuration = BBR_ULA_C | BBR_GUA_C | BBR_GUA_ROUTE;
|
||||
|
||||
static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d};
|
||||
static uint8_t static_ula_address[16] = {0};
|
||||
|
@ -109,15 +113,10 @@ static void ws_bbr_rpl_root_start(uint8_t *dodag_id)
|
|||
tr_err("RPL dodag init failed");
|
||||
return;
|
||||
}
|
||||
memcpy(static_dodag_id, dodag_id, 16);
|
||||
|
||||
// RPL memory limits set larger for Border router
|
||||
rpl_control_set_memory_limits(64 * 1024, 0);
|
||||
|
||||
uint8_t t_flags = PIO_A;
|
||||
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, t_flags, 7200, 7200, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, 0x18, 7200, false);
|
||||
// Save configured static id to check for changes later
|
||||
memcpy(static_dodag_id, dodag_id, 16);
|
||||
}
|
||||
|
||||
static void ws_bbr_rpl_root_stop(void)
|
||||
|
@ -130,6 +129,17 @@ static void ws_bbr_rpl_root_stop(void)
|
|||
memset(global_dodag_id, 0, 16);
|
||||
}
|
||||
|
||||
static void ws_bbr_ula_prefix_enable(uint8_t *dodag_id)
|
||||
{
|
||||
tr_info("RPL ula prefix start");
|
||||
|
||||
uint8_t t_flags = PIO_A;
|
||||
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, t_flags, 7200, 7200, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, 0x18, 7200, false);
|
||||
}
|
||||
|
||||
|
||||
static int ws_border_router_proxy_validate(int8_t interface_id, uint8_t *address)
|
||||
{
|
||||
|
||||
|
@ -170,12 +180,13 @@ static int ws_bbr_static_ula_create(protocol_interface_info_entry_t *cur)
|
|||
tr_info("BBR generate ula prefix");
|
||||
|
||||
// This address is only used if no other address available.
|
||||
if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, static_dodag_prefix, 64, 0xffffffff, 0, true, SLAAC_IID_FIXED);
|
||||
if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, static_dodag_prefix, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED);
|
||||
if (!add_entry) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(static_ula_address, add_entry->address, 16);
|
||||
tr_info("BBR generate ula prefix addr %s", trace_ipv6(static_ula_address));
|
||||
addr_policy_table_add_entry(static_dodag_prefix, 64, 2, WS_NON_PREFFRED_LABEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -266,6 +277,32 @@ static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_upd
|
|||
return true;
|
||||
}
|
||||
|
||||
static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id)
|
||||
{
|
||||
uint8_t ll[16];
|
||||
memcpy(ll, ADDR_LINK_LOCAL_PREFIX, 8);
|
||||
memcpy(&ll[8], cur->mac, 8);
|
||||
ll[8] ^= 2;
|
||||
|
||||
tr_debug("DHCP server activate %s", trace_ipv6(global_id));
|
||||
|
||||
if (DHCPv6_server_service_init(cur->id, global_id, cur->mac, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) != 0) {
|
||||
tr_error("DHCPv6 Server create fail");
|
||||
return;
|
||||
}
|
||||
DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb);
|
||||
|
||||
DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true);
|
||||
DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, 7200);
|
||||
|
||||
ws_dhcp_client_address_request(cur, global_id, ll);
|
||||
}
|
||||
static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id)
|
||||
{
|
||||
tr_debug("DHCP server deactivate %s", trace_ipv6(global_id));
|
||||
DHCPv6_server_service_delete(cur->id, global_id, false);
|
||||
|
||||
}
|
||||
|
||||
static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
@ -277,56 +314,73 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
|||
|
||||
ws_bbr_dodag_get(cur, static_id, global_id);
|
||||
|
||||
// Check if we need to wait for Global ID
|
||||
if (configuration & BBR_GUA_WAIT) {
|
||||
if (memcmp(global_dodag_id, ADDR_UNSPECIFIED, 16) == 0 &&
|
||||
memcmp(global_id, ADDR_UNSPECIFIED, 16) == 0) {
|
||||
// We need to wait for Global connectivity to start anything
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(static_dodag_id, static_id, 16) != 0) {
|
||||
// Static id updated or first setup
|
||||
ws_bbr_rpl_root_start(static_id);
|
||||
if (configuration & BBR_ULA_C) {
|
||||
// Start static ULA prefix and routing always
|
||||
ws_bbr_ula_prefix_enable(static_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(global_dodag_id, global_id, 16) != 0) {
|
||||
// Global prefix changed
|
||||
if (memcmp(global_dodag_id, ADDR_UNSPECIFIED, 16) != 0) {
|
||||
// TODO remove old global prefix
|
||||
tr_info("RPL GUA deactivate %s", trace_ipv6(global_dodag_id));
|
||||
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, PIO_A, 7200, 7200, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, 0x18, 7200, false);
|
||||
|
||||
// Old backbone information is deleted after 120 seconds
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, 120, true);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 120, 0, true);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 120, true);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, 0, true);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 0, 0, true);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 0, true);
|
||||
ipv6_route_add_with_info(global_dodag_id, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 120, 0);
|
||||
DHCPv6_server_service_delete(cur->id, global_dodag_id, false);
|
||||
|
||||
// Set old addresses to deferred and timeout
|
||||
ws_dhcp_client_address_delete(cur, global_dodag_id);
|
||||
ws_bbr_dhcp_server_stop(cur, global_dodag_id);
|
||||
}
|
||||
// TODO add global prefix
|
||||
if (memcmp(global_id, ADDR_UNSPECIFIED, 16) != 0) {
|
||||
//DHCPv6 Server set here
|
||||
//Interface LL64 address
|
||||
uint8_t ll[16];
|
||||
memcpy(ll, ADDR_LINK_LOCAL_PREFIX, 8);
|
||||
memcpy(&ll[8], cur->mac, 8);
|
||||
ll[8] ^= 2;
|
||||
|
||||
if (DHCPv6_server_service_init(cur->id, global_id, cur->mac, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) != 0) {
|
||||
tr_error("DHCPv6 Server create fail");
|
||||
return;
|
||||
}
|
||||
DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb);
|
||||
|
||||
DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true);
|
||||
DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, 7200);
|
||||
|
||||
tr_info("RPL GUA activate %s", trace_ipv6(global_id));
|
||||
ws_dhcp_client_address_request(cur, global_id, ll);
|
||||
//DHCPv6 Server flags set 0 by default
|
||||
uint8_t t_flags = 0;
|
||||
|
||||
// Add default route to RPL
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, 7200, false);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, PIO_A, 7200, 0, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, 0x18, 7200, false);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_id, 64, 0, 7200, 7200, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_id, 64, 0, 7200, false);
|
||||
// Enable default routing to backbone
|
||||
ipv6_route_add_with_info(global_id, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0xffffffff, 0);
|
||||
|
||||
if (configuration & BBR_GUA_SLAAC) {
|
||||
// GUA prefix is using SLAAC so no DHCP started and set correct flags for prefix
|
||||
t_flags = PIO_A;
|
||||
icmpv6_slaac_address_add(cur, global_id, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED);
|
||||
} else {
|
||||
ws_bbr_dhcp_server_start(cur, global_id);
|
||||
}
|
||||
|
||||
if (configuration & BBR_GUA_C) {
|
||||
// Add also global prefix and route to RPL
|
||||
uint32_t valid_lifetime;
|
||||
if (t_flags & PIO_A) {
|
||||
valid_lifetime = 7200;
|
||||
} else {
|
||||
valid_lifetime = 0;
|
||||
}
|
||||
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_id, 64, t_flags, valid_lifetime, valid_lifetime, false);
|
||||
|
||||
}
|
||||
if (configuration & BBR_GUA_ROUTE) {
|
||||
// Add also global prefix and route to RPL
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_id, 64, 0, 7200, false);
|
||||
}
|
||||
|
||||
}
|
||||
memcpy(global_dodag_id, global_id, 16);
|
||||
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
|
||||
|
@ -420,12 +474,44 @@ uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur)
|
|||
if (test_pan_size_override != 0xffff) {
|
||||
return test_pan_size_override;
|
||||
}
|
||||
//
|
||||
const uint8_t *prefix_ptr;
|
||||
if ((configuration & (BBR_ULA_C | BBR_GUA_C)) == BBR_GUA_C) {
|
||||
//Use just GUA Prefix
|
||||
prefix_ptr = global_dodag_id;
|
||||
|
||||
rpl_control_get_instance_dao_target_count(cur->rpl_domain, RPL_INSTANCE_ID, NULL, &result);
|
||||
} else {
|
||||
//Use ULA for indentifier
|
||||
prefix_ptr = static_dodag_id;
|
||||
}
|
||||
|
||||
rpl_control_get_instance_dao_target_count(cur->rpl_domain, RPL_INSTANCE_ID, NULL, prefix_ptr, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
||||
(void)cur;
|
||||
uint8_t global_address[16];
|
||||
|
||||
if (backbone_interface_id < 0) {
|
||||
// No need to wait for backbone
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((configuration & BBR_BB_WAIT) != BBR_BB_WAIT) {
|
||||
// No need to wait for backbone
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arm_net_address_get(backbone_interface_id, ADDR_IPV6_GP, global_address) != 0) {
|
||||
// No global prefix available
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif //HAVE_WS_BORDER_ROUTER
|
||||
|
||||
/* Public APIs
|
||||
|
@ -471,18 +557,44 @@ void ws_bbr_stop(int8_t interface_id)
|
|||
(void)interface_id;
|
||||
#endif
|
||||
}
|
||||
int ws_bbr_configure(int8_t interface_id, uint16_t options)
|
||||
{
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
|
||||
(void)interface_id;
|
||||
if (protocol_6lowpan_rpl_root_dodag &&
|
||||
options != configuration) {
|
||||
//Configuration changed delete previus setup
|
||||
ws_bbr_rpl_root_stop();
|
||||
}
|
||||
configuration = options;
|
||||
return 0;
|
||||
#else
|
||||
(void)interface_id;
|
||||
(void)options;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) eui64;
|
||||
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
return ws_pae_controller_node_keys_remove(interface_id, eui64);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ws_bbr_node_access_revoke_start(int8_t interface_id)
|
||||
{
|
||||
(void) interface_id;
|
||||
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
return ws_pae_controller_node_access_revoke_start(interface_id);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -29,13 +29,15 @@ uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur);
|
|||
|
||||
void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy);
|
||||
|
||||
bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define ws_bbr_seconds_timer( cur, seconds)
|
||||
#define ws_bbr_pan_size(cur) 0
|
||||
#define ws_bbr_rpl_config( imin, doubling, redundancy);
|
||||
#define ws_bbr_rpl_config( imin, doubling, redundancy)
|
||||
#define ws_bbr_ready_to_start(cur) true
|
||||
|
||||
#endif //HAVE_WS_BORDER_ROUTER
|
||||
|
||||
|
|
|
@ -85,8 +85,21 @@ static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entr
|
|||
static uint16_t ws_bootstrap_rank_get(protocol_interface_info_entry_t *cur);
|
||||
static uint16_t ws_bootstrap_min_rank_inc_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
static void ws_bootstrap_key_insert(protocol_interface_info_entry_t *cur, uint8_t gtk_index, uint8_t *gtk);
|
||||
static void ws_bootstrap_mac_security_enable(protocol_interface_info_entry_t *cur);
|
||||
static void ws_bootstrap_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t operation, uint8_t index, uint8_t *key);
|
||||
static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint8_t slot);
|
||||
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index);
|
||||
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter);
|
||||
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, bool success);
|
||||
static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur);
|
||||
static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor);
|
||||
static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr);
|
||||
|
||||
typedef enum {
|
||||
WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/
|
||||
WS_PARENT_HARD_SYNCH, /**< Synch FHSS with latest synch information*/
|
||||
WS_EAPOL_PARENT_SYNCH, /**< Broadcast synch with EAPOL parent*/
|
||||
} ws_parent_synch_e;
|
||||
|
||||
mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interface_info_entry *interface, const uint8_t *src64)
|
||||
|
||||
|
@ -142,6 +155,9 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_
|
|||
} else if (reason == ADDR_CALLBACK_DELETED) {
|
||||
// What to do?
|
||||
// Go through address list and check if there is global address still available
|
||||
//Discover prefix policy
|
||||
addr_policy_remove_by_label(WS_NON_PREFFRED_LABEL);
|
||||
|
||||
interface->global_address_available = false;
|
||||
ns_list_foreach(if_address_entry_t, addr_str, &interface->ip_addresses) {
|
||||
if (addr_ipv6_scope(addr_str->address, interface) > IPV6_SCOPE_LINK_LOCAL) {
|
||||
|
@ -150,8 +166,14 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tr_debug("Address notification addr: %s reason: %d", trace_ipv6(addr->address), reason);
|
||||
} else if (reason == ADDR_CALLBACK_TIMER) {
|
||||
tr_debug("Address Re registration %s", trace_ipv6(addr->address));
|
||||
|
||||
if (!interface->ws_info->address_registration_event_active) {
|
||||
interface->ws_info->address_registration_event_active = true;
|
||||
tr_info("Register ARO");
|
||||
ws_bootsrap_event_trig(WS_ADDRESS_ADDED, interface->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,6 +192,21 @@ static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
|
|||
|
||||
return 0;
|
||||
}
|
||||
static void ws_nwk_event_post(protocol_interface_info_entry_t *cur, arm_nwk_interface_status_type_e posted_event)
|
||||
{
|
||||
arm_event_s event = {
|
||||
.receiver = cur->net_start_tasklet,
|
||||
.sender = protocol_read_tasklet_id(), /**< Event sender Tasklet ID */
|
||||
.event_type = ARM_LIB_NWK_INTERFACE_EVENT,
|
||||
.event_data = posted_event,
|
||||
.event_id = (int8_t) cur->id,
|
||||
.data_ptr = NULL,
|
||||
.priority = ARM_LIB_LOW_PRIORITY_EVENT,
|
||||
};
|
||||
if (eventOS_event_send(&event) != 0) {
|
||||
tr_error("nwk_net_event_post(): event send failed");
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data)
|
||||
{
|
||||
|
@ -218,8 +255,9 @@ static ws_nud_table_entry_t *ws_nud_entry_get_free(protocol_interface_info_entry
|
|||
|
||||
void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor)
|
||||
{
|
||||
ns_list_foreach(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) {
|
||||
if (entry->neighbor_info == neighbor) {
|
||||
ws_nud_table_entry_t *entry = ws_nud_entry_discover(cur, neighbor);
|
||||
|
||||
if (entry) {
|
||||
mac_neighbor_table_entry_t *mac_neighbor = neighbor;
|
||||
ns_list_remove(&cur->ws_info->active_nud_process, entry);
|
||||
ns_list_add_to_end(&cur->ws_info->free_nud_entries, entry);
|
||||
|
@ -228,11 +266,21 @@ void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neig
|
|||
}
|
||||
|
||||
mac_neighbor_table_neighbor_connected(mac_neighbor_info(cur), mac_neighbor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor)
|
||||
{
|
||||
ns_list_foreach(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) {
|
||||
if (entry->neighbor_info == neighbor) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void ws_nud_state_clean(protocol_interface_info_entry_t *cur, ws_nud_table_entry_t *entry)
|
||||
{
|
||||
mac_neighbor_table_entry_t *neighbor = entry->neighbor_info;
|
||||
|
@ -244,6 +292,14 @@ static void ws_nud_state_clean(protocol_interface_info_entry_t *cur, ws_nud_tabl
|
|||
}
|
||||
}
|
||||
|
||||
static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr)
|
||||
{
|
||||
ws_nud_table_entry_t *nud_entry = ws_nud_entry_discover(cur, entry_ptr);
|
||||
if (nud_entry) {
|
||||
ws_nud_state_clean(cur, nud_entry);
|
||||
}
|
||||
}
|
||||
|
||||
static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor)
|
||||
{
|
||||
//Send NS
|
||||
|
@ -444,8 +500,6 @@ static int8_t ws_fhss_discovery_configure(protocol_interface_info_entry_t *cur)
|
|||
fhss_configuration.fhss_broadcast_interval = 0;
|
||||
uint8_t tmp_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels);
|
||||
uint8_t tmp_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels);
|
||||
memset(fhss_configuration.channel_mask, 0, sizeof(uint32_t) * 8);
|
||||
channel_list_set_channel(fhss_configuration.channel_mask, tmp_uc_fixed_channel, true);
|
||||
fhss_configuration.unicast_fixed_channel = tmp_uc_fixed_channel;
|
||||
fhss_configuration.broadcast_fixed_channel = tmp_bc_fixed_channel;
|
||||
ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration);
|
||||
|
@ -477,7 +531,7 @@ static int8_t ws_fhss_enable(protocol_interface_info_entry_t *cur)
|
|||
/* Sets the parent and broadcast schedule we are following
|
||||
*
|
||||
*/
|
||||
static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry *cur, llc_neighbour_req_t *neighbor_info, bool force_synch)
|
||||
static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry *cur, llc_neighbour_req_t *neighbor_info, ws_parent_synch_e synch_req)
|
||||
{
|
||||
|
||||
fhss_ws_configuration_t fhss_configuration;
|
||||
|
@ -490,7 +544,9 @@ static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry
|
|||
|
||||
// Learning broadcast network configuration
|
||||
if (neighbor_info->ws_neighbor->broadcast_shedule_info_stored) {
|
||||
if (synch_req != WS_EAPOL_PARENT_SYNCH) {
|
||||
ws_fhss_set_defaults(cur, &fhss_configuration);
|
||||
}
|
||||
fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_channel_function;
|
||||
if (fhss_configuration.ws_bc_channel_function == WS_FIXED_CHANNEL) {
|
||||
cur->ws_info->hopping_schdule.bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel;
|
||||
|
@ -500,18 +556,36 @@ static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry
|
|||
fhss_configuration.fhss_bc_dwell_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_dwell_interval;
|
||||
fhss_configuration.fhss_broadcast_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_interval;
|
||||
fhss_configuration.broadcast_fixed_channel = cur->ws_info->fhss_bc_fixed_channel;
|
||||
|
||||
neighbor_info->ws_neighbor->synch_done = true;
|
||||
}
|
||||
|
||||
ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration);
|
||||
|
||||
// We have broadcast schedule set up set the broadcast parent schedule
|
||||
ns_fhss_ws_set_parent(cur->ws_info->fhss_api, neighbor_info->neighbor->mac64, &neighbor_info->ws_neighbor->fhss_data.bc_timing_info, force_synch);
|
||||
ns_fhss_ws_set_parent(cur->ws_info->fhss_api, neighbor_info->neighbor->mac64, &neighbor_info->ws_neighbor->fhss_data.bc_timing_info, synch_req != WS_PARENT_SOFT_SYNCH);
|
||||
|
||||
// Update LLC to follow updated fhss settings
|
||||
ws_bootstrap_llc_hopping_update(cur, &fhss_configuration);
|
||||
}
|
||||
|
||||
void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, llc_neighbour_req_t *neighbor_info)
|
||||
{
|
||||
if (cur->ws_info->configuration_learned || !neighbor_info->ws_neighbor->broadcast_shedule_info_stored || !neighbor_info->ws_neighbor->broadcast_timing_info_stored) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(neighbor_info->neighbor->mac64, cur->ws_info->parent_info.addr, 8)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Store Brodacst Shedule
|
||||
if (!neighbor_info->ws_neighbor->synch_done) {
|
||||
ws_bootstrap_primary_parent_set(cur, neighbor_info, WS_EAPOL_PARENT_SYNCH);
|
||||
} else {
|
||||
ns_fhss_ws_set_parent(cur->ws_info->fhss_api, neighbor_info->neighbor->mac64, &neighbor_info->ws_neighbor->fhss_data.bc_timing_info, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
// Configure EUI64 for MAC if missing
|
||||
|
@ -572,10 +646,13 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
|
|||
}
|
||||
} else {
|
||||
|
||||
if (!ws_neighbour || !etx_entry || etx_entry->etx_samples < 1 ||
|
||||
!ws_neighbour->candidate_parent) {
|
||||
if (!ws_neighbour || !etx_entry || etx_entry->etx_samples < 1 /*||
|
||||
!ws_neighbour->candidate_parent*/) {
|
||||
// if RSL value is not good enough candidate parent flag is removed and device not accepted as parent
|
||||
//tr_debug("ws_etx_read not valid parent");
|
||||
if (etx_entry && etx_entry->etx_samples) {
|
||||
tr_debug("ws_etx_read not valid %u RSL IN(%u), %u RSL out(%u)", ws_neighbor_class_rsl_in_get(ws_neighbour), ws_neighbour->rsl_in, ws_neighbor_class_rsl_out_get(ws_neighbour), ws_neighbour->rsl_out);
|
||||
}
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
@ -589,6 +666,7 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
|
|||
} else {
|
||||
if (!ws_neighbour->broadcast_timing_info_stored) {
|
||||
//Global shedule is stored already
|
||||
tr_debug("ws_etx_read not valid NO BTI");
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
@ -598,10 +676,6 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
|
|||
if (etx == 0) {
|
||||
return 0xffff;
|
||||
}
|
||||
if (etx > 0x800) {
|
||||
// Wi-SUN section 6.2.3.1.6.1 says ETX can only be maximum of 1024 (8*128) in RPL units, ie 8.0.
|
||||
etx = 0x800;
|
||||
}
|
||||
|
||||
//tr_debug("ws_etx_read etx:%d", etx);
|
||||
return etx;
|
||||
|
@ -624,7 +698,8 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
|
|||
return -3;
|
||||
}
|
||||
|
||||
|
||||
//Enable Power bootup timer setup
|
||||
cur->ws_info->power_up_setup = true;
|
||||
// Save FHSS api
|
||||
cur->ws_info->fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api);
|
||||
|
||||
|
@ -642,14 +717,16 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
|
|||
/* Disable SLLAO send/mandatory receive with the ARO */
|
||||
cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true;
|
||||
/* Omit sending of NA if ARO SUCCESS */
|
||||
cur->ipv6_neighbour_cache.omit_aro_success = true;
|
||||
cur->ipv6_neighbour_cache.omit_na_aro_success = true;
|
||||
/* Omit sending of NA and consider ACK to be success */
|
||||
cur->ipv6_neighbour_cache.omit_na = true;
|
||||
// do not process AROs from NA. This is overriden by Wi-SUN specific failure handling
|
||||
cur->ipv6_neighbour_cache.recv_na_aro = false;
|
||||
/* Disable NUD Probes */
|
||||
cur->ipv6_neighbour_cache.send_nud_probes = false;
|
||||
cur->ipv6_neighbour_cache.probe_avoided_routers = true;
|
||||
dhcp_client_init(cur->id);
|
||||
dhcp_client_configure(cur->id, true); //RENEW uses SOLICIT
|
||||
dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used.
|
||||
dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC);
|
||||
|
||||
|
||||
|
@ -819,6 +896,7 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
|
|||
|
||||
// Save route cost for all neighbours
|
||||
llc_neighbour_req_t neighbor_info;
|
||||
neighbor_info.neighbor = NULL;
|
||||
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
|
||||
neighbor_info.ws_neighbor->routing_cost = pan_information.routing_cost;
|
||||
}
|
||||
|
@ -848,14 +926,14 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
|
|||
uint16_t pan_cost = (pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (pan_information.pan_size / PS_WEIGHT_FACTOR);
|
||||
uint16_t current_pan_cost = (cur->ws_info->parent_info.pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (cur->ws_info->parent_info.pan_information.pan_size / PS_WEIGHT_FACTOR);
|
||||
if (current_pan_cost < pan_cost) {
|
||||
tr_info("EAPOL target dropped Higher Pan cost");
|
||||
tr_info("EAPOL target dropped Higher Pan cost %u > %u current", pan_cost, current_pan_cost);
|
||||
return;
|
||||
}
|
||||
|
||||
// If pan cost is the same then we select the one we hear highest
|
||||
if (current_pan_cost == pan_cost &&
|
||||
cur->ws_info->parent_info.signal_dbm > data->signal_dbm) {
|
||||
tr_info("EAPOL target dropped Lower link quality");
|
||||
tr_info("EAPOL target dropped Lower link quality %u < %u current", data->signal_dbm, cur->ws_info->parent_info.signal_dbm);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -895,13 +973,17 @@ parent_selected:
|
|||
ws_bootstrap_pan_advertisement_analyse_active(cur, &pan_information);
|
||||
|
||||
// Learn latest network information
|
||||
if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && neighbor_info.neighbor) {
|
||||
|
||||
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
|
||||
cur->ws_info->pan_information.pan_size = pan_information.pan_size;
|
||||
cur->ws_info->pan_information.routing_cost = pan_information.routing_cost;
|
||||
cur->ws_info->pan_information.rpl_routing_method = pan_information.rpl_routing_method;
|
||||
cur->ws_info->pan_information.use_parent_bs = pan_information.use_parent_bs;
|
||||
cur->ws_info->pan_information.version = pan_information.version;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us)
|
||||
|
@ -930,7 +1012,6 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
|||
ws_bs_ie_t ws_bs_ie;
|
||||
uint8_t *gtkhash_ptr;
|
||||
|
||||
|
||||
if (data->SrcPANId != cur->ws_info->network_pan_id) {
|
||||
tr_debug("Wrong PAN id r:%u own:%u", data->SrcPANId, cur->ws_info->network_pan_id);
|
||||
return;
|
||||
|
@ -986,19 +1067,26 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
|||
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
|
||||
|
||||
if (cur->ws_info->configuration_learned) {
|
||||
// received version is lower se we need to reset the trickle
|
||||
tr_info("PAN Config analyse own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version);
|
||||
if (cur->ws_info->pan_information.pan_version == pan_version) {
|
||||
// Same version heard so it is consistent
|
||||
trickle_consistent_heard(&cur->ws_info->trickle_pan_config);
|
||||
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
|
||||
ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_SOFT_SYNCH);
|
||||
}
|
||||
// no need to process more
|
||||
return;
|
||||
} else {
|
||||
tr_info("different pan version heard");
|
||||
// received version is different so we need to reset the trickle
|
||||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery);
|
||||
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
|
||||
ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH);
|
||||
}
|
||||
if (common_serial_number_greater_16(cur->ws_info->pan_information.pan_version, pan_version)) {
|
||||
// older version heard ignoring the message
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
|
@ -1006,28 +1094,18 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
|||
return;
|
||||
}
|
||||
|
||||
if (cur->ws_info->configuration_learned) {
|
||||
bool old_version = cur->ws_info->pan_information.pan_version == pan_version;
|
||||
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
|
||||
// RPL priority parent configuration we must update FHSS data
|
||||
//Update synch to primary parent allways to update broadcast shedule and timing
|
||||
ws_bootstrap_primary_parent_set(cur, &neighbor_info, !old_version);
|
||||
}
|
||||
|
||||
if (old_version) {
|
||||
// No new information
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Learn new information from border router
|
||||
* Learn new information from neighbor
|
||||
*/
|
||||
tr_info("Updated PAN configuration heard");
|
||||
tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version);
|
||||
|
||||
// restart PAN version timer
|
||||
cur->ws_info->pan_version_timeout_timer = PAN_VERSION_TIMEOUT;
|
||||
cur->ws_info->pan_information.pan_version = pan_version;
|
||||
memcpy(cur->ws_info->gtkhash, gtkhash_ptr, 32);
|
||||
|
||||
ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr);
|
||||
|
||||
ws_pae_controller_nw_key_index_update(cur, data->Key.KeyIndex - 1);
|
||||
|
||||
if (!cur->ws_info->configuration_learned) {
|
||||
// Generate own hopping schedules Follow first parent broadcast and plans and also use same unicast dwell
|
||||
|
@ -1036,7 +1114,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
|||
// return to state machine after 1-2 s
|
||||
cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, 20);
|
||||
// enable frequency hopping for unicast channel and start listening first neighbour
|
||||
ws_bootstrap_primary_parent_set(cur, &neighbor_info, true);
|
||||
ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH);
|
||||
// set neighbor as priority parent clear if there is others
|
||||
protocol_6lowpan_neighbor_priority_clear_all(cur->id, PRIORITY_1ST);
|
||||
neighbor_info.neighbor->link_role = PRIORITY_PARENT_NEIGHBOUR;
|
||||
|
@ -1060,13 +1138,13 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in
|
|||
*/
|
||||
|
||||
llc_neighbour_req_t neighbor_info;
|
||||
if (!ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
|
||||
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index);
|
||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
|
||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A consistent transmission is defined as a PAN Configuration Solicit with
|
||||
|
@ -1175,19 +1253,19 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c
|
|||
switch (message_type) {
|
||||
case WS_FT_PAN_ADVERT:
|
||||
// Analyse Advertisement
|
||||
tr_debug("received ADVERT");
|
||||
tr_info("received ADVERT Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
|
||||
ws_bootstrap_pan_advertisement_analyse(cur, data, ie_ext, &ws_utt, &ws_us);
|
||||
break;
|
||||
case WS_FT_PAN_ADVERT_SOL:
|
||||
tr_debug("received ADVERT SOL");
|
||||
tr_info("received ADVERT SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
|
||||
ws_bootstrap_pan_advertisement_solicit_analyse(cur, data, &ws_utt, &ws_us);
|
||||
break;
|
||||
case WS_FT_PAN_CONF:
|
||||
tr_debug("received CONFIG");
|
||||
tr_info("received CONFIG Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
|
||||
ws_bootstrap_pan_config_analyse(cur, data, ie_ext, &ws_utt, &ws_us);
|
||||
break;
|
||||
default:
|
||||
tr_debug("received CONFIG SOL");
|
||||
tr_info("received CONFIG SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
|
||||
ws_bootstrap_pan_config_solicit_analyse(cur, data, &ws_utt, &ws_us);
|
||||
break;
|
||||
}
|
||||
|
@ -1221,6 +1299,8 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cur->trusted_device) {
|
||||
|
||||
if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) {
|
||||
// We have registered entry so we have been selected as parent
|
||||
continue;
|
||||
|
@ -1233,7 +1313,18 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
|
|||
// Possible parent is limited to 3 by default?
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (cur->trusted_device) {
|
||||
neighbor_entry_ptr = cur;
|
||||
} else {
|
||||
if (cur->link_lifetime - cur->lifetime > WS_NEIGHBOR_NOT_TRUSTED_LINK_TIMEOUT) {
|
||||
//Accept only Enough Old not trusted Device
|
||||
neighbor_entry_ptr = cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (neighbor_entry_ptr) {
|
||||
tr_info("dropped oldest neighbour %s", trace_array(neighbor_entry_ptr->mac64, 8));
|
||||
|
@ -1299,6 +1390,10 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt
|
|||
protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_ptr->mac16);
|
||||
protocol_6lowpan_release_long_link_address_from_neighcache(cur, entry_ptr->mac64);
|
||||
}
|
||||
|
||||
//NUD Process Clear Here
|
||||
ws_nud_entry_remove(cur, entry_ptr);
|
||||
|
||||
ws_bootstrap_neighbor_delete(cur, entry_ptr->index);
|
||||
}
|
||||
|
||||
|
@ -1387,6 +1482,13 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
|
|||
if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) {
|
||||
return -1;
|
||||
}
|
||||
if (!etx_cached_etx_parameter_set(WS_ETX_MIN_WAIT_TIME, WS_ETX_MIN_SAMPLE_COUNT)) {
|
||||
etx_storage_list_allocate(cur->id, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
etx_max_update_set(WS_ETX_MAX_UPDATE);
|
||||
|
||||
if (blacklist_init() != 0) {
|
||||
tr_err("MLE blacklist init failed.");
|
||||
return -1;
|
||||
|
@ -1452,7 +1554,7 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
|
|||
ret_val = -4;
|
||||
goto init_fail;
|
||||
}
|
||||
if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_key_insert) < 0) {
|
||||
if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_pan_version_increment) < 0) {
|
||||
ret_val = -4;
|
||||
goto init_fail;
|
||||
}
|
||||
|
@ -1542,26 +1644,32 @@ int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_chan
|
|||
set_request.value_pointer = &ack_wait_symbols;
|
||||
set_request.value_size = sizeof(ack_wait_symbols);
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
|
||||
// Set multi CSMA-CA configuration
|
||||
mlme_multi_csma_ca_param_t multi_csma_params = {WS_NUMBER_OF_CSMA_PERIODS, WS_CSMA_MULTI_CCA_INTERVAL};
|
||||
set_request.attr = macMultiCSMAParameters;
|
||||
set_request.value_pointer = &multi_csma_params;
|
||||
set_request.value_size = sizeof(mlme_multi_csma_ca_param_t);
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_bootstrap_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
tr_warn("ARO registration Failure %s", trace_ipv6(ll_address));
|
||||
|
||||
blacklist_update(ll_address, false);
|
||||
rpl_control_neighbor_delete(cur, ll_address);
|
||||
|
||||
mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll_address, false, NULL);
|
||||
|
||||
if (mac_neighbor) {
|
||||
ws_bootstrap_neighbor_delete(cur, mac_neighbor->index);
|
||||
// TODO Add to blacklist
|
||||
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), mac_neighbor);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
blacklist_update(ll_address, false);
|
||||
rpl_control_neighbor_delete(cur, ll_address);
|
||||
ws_bootstrap_neighbor_remove(cur, ll_address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid, bool coordinator)
|
||||
{
|
||||
|
@ -1592,6 +1700,7 @@ static void ws_bootstrap_fhss_activate(protocol_interface_info_entry_t *cur)
|
|||
tr_debug("MAC init");
|
||||
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
|
||||
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
|
||||
ws_bootstrap_mac_security_enable(cur);
|
||||
ws_bootstrap_mac_activate(cur, cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->network_pan_id, true);
|
||||
return;
|
||||
}
|
||||
|
@ -1619,7 +1728,8 @@ static void ws_bootstrap_network_configuration_learn(protocol_interface_info_ent
|
|||
|
||||
// Timing information can be modified here
|
||||
ws_llc_set_pan_information_pointer(cur, &cur->ws_info->pan_information);
|
||||
ws_llc_set_gtkhash(cur, cur->ws_info->gtkhash);
|
||||
uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur);
|
||||
ws_llc_set_gtkhash(cur, gtkhash);
|
||||
// TODO update own fhss schedules we are starting to follow first parent
|
||||
|
||||
return;
|
||||
|
@ -1728,32 +1838,12 @@ static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[
|
|||
tr_debug("DHCPv6 %s status %u", trace_ipv6(dhcp_addr), register_status);
|
||||
}
|
||||
|
||||
static bool ws_address_entry_available(uint8_t *prefixPtr, if_address_list_t *list)
|
||||
{
|
||||
bool addressReady = false;
|
||||
ns_list_foreach(if_address_entry_t, entry, list) {
|
||||
if (prefixPtr) {
|
||||
if (memcmp(entry->address, prefixPtr, 8) == 0) {
|
||||
addressReady = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (entry->source == ADDR_SOURCE_DHCP) {
|
||||
addressReady = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return addressReady;
|
||||
}
|
||||
|
||||
void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local)
|
||||
{
|
||||
if (!ws_address_entry_available(prefix, &cur->ip_addresses)) {
|
||||
if (dhcp_client_get_global_address(cur->id, parent_link_local, prefix, cur->mac, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE, ws_dhcp_client_global_adress_cb) != 0) {
|
||||
tr_error("DHCPp client request fail");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix)
|
||||
|
@ -1778,24 +1868,30 @@ static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t
|
|||
* from a prefix advertised by a parent.
|
||||
*/
|
||||
if (prefix->options & PIO_A) {
|
||||
|
||||
if (parent_link_local) {
|
||||
if (icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime) != 0) {
|
||||
ipv6_interface_slaac_handler(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime);
|
||||
/*
|
||||
* Give SLAAC addresses a different label and low precedence to indicate that
|
||||
* they probably shouldn't be used for external traffic. SLAAC use in Wi-SUN is non-standard,
|
||||
* and we use it for mesh-local traffic we should prefer any DHCP-assigned addresses
|
||||
* for talking to the outside world
|
||||
*
|
||||
*/
|
||||
addr_policy_table_add_entry(prefix->prefix, prefix->prefix_len, 2, WS_NON_PREFFRED_LABEL);
|
||||
}
|
||||
} else {
|
||||
icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, 0, 0);
|
||||
}
|
||||
} else if (prefix->prefix_len) {
|
||||
if (prefix->preftime == 0) {
|
||||
// Delete all pending transactions from DHCP
|
||||
// TODO this also deletes the address even when lifetime would allow it to be present
|
||||
dhcp_client_global_address_delete(cur->id, NULL, prefix->prefix);
|
||||
} else {
|
||||
// Create new address using DHCP
|
||||
if (parent_link_local) {
|
||||
ws_dhcp_client_address_request(cur, prefix->prefix, parent_link_local);
|
||||
}
|
||||
// If we have addresses generated we update the lifetimes always
|
||||
ns_list_foreach(if_address_entry_t, entry, &cur->ip_addresses) {
|
||||
if (entry->prefix_len == prefix->prefix_len && bitsequal(entry->address, prefix->prefix, prefix->prefix_len)) {
|
||||
entry->preferred_lifetime = prefix->preftime;
|
||||
entry->valid_lifetime = prefix->lifetime;
|
||||
}
|
||||
} else {
|
||||
/* Deprecate address and remove client */
|
||||
tr_debug("Prefix invalidation %s", trace_ipv6(prefix->prefix));
|
||||
dhcp_client_global_address_delete(cur->id, NULL, prefix->prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1839,10 +1935,13 @@ static void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur)
|
|||
{
|
||||
cur->ws_info->trickle_pa_running = true;
|
||||
trickle_start(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery);
|
||||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery);
|
||||
cur->ws_info->trickle_pc_running = true;
|
||||
trickle_start(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery);
|
||||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
cur->ws_info->pan_version_timer = 1;
|
||||
}
|
||||
|
||||
// Start network scan
|
||||
|
@ -1870,7 +1969,19 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
|
|||
// Reset advertisement solicit trickle to start discovering network
|
||||
cur->ws_info->trickle_pas_running = true;
|
||||
trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
|
||||
if (cur->ws_info->power_up_setup) {
|
||||
cur->ws_info->power_up_setup = false;
|
||||
tr_debug("PAS init I %u and t %u", cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t);
|
||||
} else {
|
||||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
|
||||
}
|
||||
|
||||
if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) != INTERFACE_NWK_BOOTSRAP_ACTIVE) {
|
||||
// we have sent bootstrap ready event and now
|
||||
// restarted discovery so bootstrap down event is sent
|
||||
cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE;
|
||||
ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN);
|
||||
}
|
||||
|
||||
// Discovery statemachine is checkked after two trickle interval
|
||||
cur->bootsrap_state_machine_cnt = 2 * cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
|
||||
|
@ -1879,25 +1990,38 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
|
|||
// Start authentication
|
||||
static void ws_bootstrap_start_authentication(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
tr_debug("authentication start");
|
||||
// Set PAN ID and network name to controller
|
||||
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name);
|
||||
|
||||
ws_pae_controller_authenticate(cur);
|
||||
}
|
||||
|
||||
|
||||
static void ws_bootstrap_key_insert(protocol_interface_info_entry_t *cur, uint8_t gtk_index, uint8_t *gtk)
|
||||
static void ws_bootstrap_mac_security_enable(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
// Convert GTK to Group AES Key (GAK)
|
||||
|
||||
// Verify HASH etc.
|
||||
|
||||
// Check index, for now only reacts to keys of index 0
|
||||
if (gtk_index == 0) {
|
||||
mac_helper_security_key_clean(cur);
|
||||
mac_helper_default_security_level_set(cur, AES_SECURITY_LEVEL_ENC_MIC64);
|
||||
mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX);
|
||||
//Set Keys
|
||||
mac_helper_security_default_key_set(cur, gtk, gtk_index + 1, MAC_KEY_ID_MODE_IDX);
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_bootstrap_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t slot, uint8_t index, uint8_t *key)
|
||||
{
|
||||
mac_helper_security_key_to_descriptor_set(cur, key, index + 1, slot);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint8_t slot)
|
||||
{
|
||||
mac_helper_security_key_descriptor_clear(cur, slot);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index)
|
||||
{
|
||||
// Set send key
|
||||
mac_helper_security_auto_request_key_index_set(cur, index + 1);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter)
|
||||
{
|
||||
// Set frame counter
|
||||
mac_helper_link_frame_counter_set(cur->id, counter);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, bool success)
|
||||
|
@ -1955,7 +2079,7 @@ void ws_bootstrap_event_configuration_start(protocol_interface_info_entry_t *cur
|
|||
}
|
||||
void ws_bootstrap_event_authentication_start(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
ws_bootsrap_event_trig(WS_AUTHENTICATION_START, cur->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL);
|
||||
ws_bootstrap_state_change(cur, ER_PANA_AUTH);
|
||||
}
|
||||
void ws_bootstrap_event_operation_start(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
@ -2155,6 +2279,13 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
|||
|
||||
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
tr_debug("Border router start network");
|
||||
|
||||
if (!ws_bbr_ready_to_start(cur)) {
|
||||
// Wi-SUN not started yet we wait for Border router permission
|
||||
ws_bootstrap_state_change(cur, ER_WAIT_RESTART);
|
||||
cur->nwk_nd_re_scan_count = randLIB_get_random_in_range(40, 100);
|
||||
return;
|
||||
}
|
||||
ws_pae_controller_auth_init(cur);
|
||||
|
||||
// Randomize fixed channels. Only used if channel plan is fixed.
|
||||
|
@ -2167,7 +2298,9 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
|||
cur->ws_info->pan_information.rpl_routing_method = true;
|
||||
cur->ws_info->pan_information.use_parent_bs = true;
|
||||
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
|
||||
ws_llc_set_gtkhash(cur, cur->ws_info->gtkhash);
|
||||
|
||||
uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur);
|
||||
ws_llc_set_gtkhash(cur, gtkhash);
|
||||
cur->ws_info->pan_version_timer = PAN_VERSION_LIFETIME;
|
||||
|
||||
// Set default parameters for FHSS when starting a discovery
|
||||
|
@ -2187,6 +2320,9 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
|||
// Set authenticator relay to port 10253 and PAE to 10254 (and to own ll address)
|
||||
ws_eapol_auth_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, ll_addr, PAE_AUTH_SOCKET_PORT);
|
||||
|
||||
// Set PAN ID and network name to controller
|
||||
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name);
|
||||
|
||||
// Set PAE port to 10254 and authenticator relay to 10253 (and to own ll address)
|
||||
ws_pae_controller_authenticator_start(cur, PAE_AUTH_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT);
|
||||
break;
|
||||
|
@ -2199,21 +2335,6 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
|||
// Start network scan
|
||||
ws_bootstrap_start_discovery(cur);
|
||||
break;
|
||||
case WS_AUTHENTICATION_START:
|
||||
tr_info("authentication start");
|
||||
// only advert sol stopped as we might be doing re authentication
|
||||
cur->ws_info->trickle_pas_running = false;
|
||||
//Add Test ecurity key and security level's
|
||||
|
||||
|
||||
// Advertisements stopped during the EAPOL
|
||||
cur->ws_info->trickle_pa_running = false;
|
||||
cur->ws_info->trickle_pc_running = false;
|
||||
cur->ws_info->trickle_pas_running = false;
|
||||
cur->ws_info->trickle_pcs_running = false;
|
||||
|
||||
ws_bootstrap_start_authentication(cur);
|
||||
break;
|
||||
|
||||
case WS_CONFIGURATION_START:
|
||||
tr_info("Configuration start");
|
||||
|
@ -2375,10 +2496,15 @@ static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp
|
|||
cur->bootsrap_state_machine_cnt = 1;
|
||||
cur->nwk_bootstrap_state = nwk_bootstrap_state;
|
||||
}
|
||||
|
||||
void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
||||
switch (cur->nwk_bootstrap_state) {
|
||||
case ER_WAIT_RESTART:
|
||||
tr_debug("WS SM:Wait for startup");
|
||||
ws_bootstrap_event_discovery_start(cur);
|
||||
break;
|
||||
case ER_ACTIVE_SCAN:
|
||||
tr_debug("WS SM:Active Scan");
|
||||
ws_bootstrap_network_scan_process(cur);
|
||||
|
@ -2387,6 +2513,19 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
|
|||
tr_debug("WS SM:configuration Scan");
|
||||
ws_bootstrap_configure_process(cur);
|
||||
break;
|
||||
case ER_PANA_AUTH:
|
||||
tr_info("authentication start");
|
||||
// only advert sol stopped as we might be doing re authentication
|
||||
cur->ws_info->trickle_pas_running = false;
|
||||
//Add Test ecurity key and security level's
|
||||
// Advertisements stopped during the EAPOL
|
||||
cur->ws_info->trickle_pa_running = false;
|
||||
cur->ws_info->trickle_pc_running = false;
|
||||
cur->ws_info->trickle_pas_running = false;
|
||||
cur->ws_info->trickle_pcs_running = false;
|
||||
|
||||
ws_bootstrap_start_authentication(cur);
|
||||
break;
|
||||
case ER_RPL_SCAN:
|
||||
tr_debug("WS SM:Wait RPL to contact DODAG root");
|
||||
ws_bootstrap_rpl_wait_process(cur);
|
||||
|
@ -2396,10 +2535,8 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
|
|||
// Bootstrap_done event to application
|
||||
nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
|
||||
break;
|
||||
|
||||
default:
|
||||
tr_warn("WS SM:Invalid state %d", cur->nwk_bootstrap_state);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2416,7 +2553,10 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t
|
|||
// send PAN Configuration solicit
|
||||
if (cur->ws_info->pas_requests > PCS_MAX) {
|
||||
// if MAX PCS sent restart discovery
|
||||
tr_debug("Restart???");
|
||||
|
||||
// Remove network keys from MAC
|
||||
ws_pae_controller_nw_keys_remove(cur);
|
||||
|
||||
ws_bootstrap_event_discovery_start(cur);
|
||||
return;
|
||||
}
|
||||
|
@ -2459,7 +2599,12 @@ void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_ne
|
|||
llc_neighbour_req_t neighbor_info;
|
||||
neighbor_info.neighbor = neighbor;
|
||||
neighbor_info.ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor->index);
|
||||
ws_bootstrap_primary_parent_set(interface, &neighbor_info, true);
|
||||
ws_bootstrap_primary_parent_set(interface, &neighbor_info, WS_PARENT_HARD_SYNCH);
|
||||
uint8_t link_local_address[16];
|
||||
memcpy(link_local_address, ADDR_LINK_LOCAL_PREFIX, 8);
|
||||
memcpy(link_local_address + 8, neighbor->mac64, 8);
|
||||
link_local_address[8] ^= 2;
|
||||
dhcp_client_server_address_update(interface->id, NULL, link_local_address);
|
||||
|
||||
ws_secondary_parent_update(interface);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ typedef enum {
|
|||
WS_INIT_EVENT = 0, /**< tasklet initializion event*/
|
||||
WS_DISCOVERY_START, /**< discovery start*/
|
||||
WS_CONFIGURATION_START, /**< configuration learn start*/
|
||||
WS_AUTHENTICATION_START, /**< authentication start*/
|
||||
WS_OPERATION_START, /**< active operation start*/
|
||||
WS_ROUTING_READY, /**< RPL routing connected to BR*/
|
||||
WS_ADDRESS_ADDED /**< Address added to IF*/
|
||||
|
@ -31,6 +30,8 @@ typedef enum {
|
|||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
struct llc_neighbour_req;
|
||||
|
||||
int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
|
||||
|
||||
void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur);
|
||||
|
@ -41,6 +42,8 @@ int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_chan
|
|||
|
||||
int ws_bootstrap_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
/*State machine transactions*/
|
||||
void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur);
|
||||
|
||||
|
@ -72,12 +75,15 @@ void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t
|
|||
|
||||
bool ws_eapol_relay_state_active(protocol_interface_info_entry_t *cur);
|
||||
|
||||
void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, struct llc_neighbour_req *neighbor_info);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
|
||||
#define ws_bootstrap_state_machine(cur)
|
||||
#define ws_bootstrap_restart(cur)
|
||||
#define ws_bootstrap_neighbor_remove(cur, ll_address)
|
||||
#define ws_bootstrap_aro_failure(cur, ll_address)
|
||||
#define ws_primary_parent_update(interface, neighbor)
|
||||
#define ws_secondary_parent_update(interface)
|
||||
|
||||
|
|
|
@ -274,6 +274,7 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
|
|||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3;
|
||||
cur->ws_info->hopping_schdule.operating_class = 2;
|
||||
ws_common_regulatory_domain_config(cur);
|
||||
cur->ws_info->network_size_config = NETWORK_SIZE_AUTOMATIC;
|
||||
ws_common_network_size_configure(cur, 10); // defaults to small network size
|
||||
|
||||
// Set defaults for the device. user can modify these.
|
||||
|
@ -302,7 +303,12 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint
|
|||
// imin: 14 (16s)
|
||||
// doublings:3 (128s)
|
||||
// redundancy; 0 Disabled
|
||||
ws_bbr_rpl_config(0, 0, 0);// set the default values
|
||||
if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) {
|
||||
ws_bbr_rpl_config(14, 3, 0);
|
||||
} else {
|
||||
ws_bbr_rpl_config(0, 0, 0);
|
||||
}
|
||||
|
||||
} else if (network_size < 300) {
|
||||
// Configure the Wi-SUN discovery trickle parameters
|
||||
cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_medium;
|
||||
|
@ -348,11 +354,19 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8
|
|||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
//Neighbor connectected update
|
||||
tr_warn("ARO registration Failure %s", trace_ipv6(ll_address));
|
||||
ws_bootstrap_aro_failure(cur, ll_address);
|
||||
}
|
||||
|
||||
void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
tr_debug("neighbor remove %s", trace_ipv6(ll_address));
|
||||
ws_bootstrap_neighbor_remove(cur, ll_address);
|
||||
}
|
||||
|
||||
bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interface)
|
||||
|
||||
|
||||
bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64)
|
||||
{
|
||||
uint8_t child_count = 0;
|
||||
uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT;
|
||||
|
@ -362,6 +376,12 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interfa
|
|||
max_child_count = test_max_child_count_override;
|
||||
}
|
||||
|
||||
//Validate Is EUI64 already allocated for any address
|
||||
if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, eui64)) {
|
||||
tr_info("Child registration from old child");
|
||||
return true;
|
||||
}
|
||||
|
||||
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) {
|
||||
|
||||
if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) {
|
||||
|
|
|
@ -79,6 +79,7 @@ typedef struct ws_info_s {
|
|||
bool trickle_pa_running: 1;
|
||||
bool trickle_pcs_running: 1;
|
||||
bool trickle_pc_running: 1;
|
||||
bool power_up_setup: 1;
|
||||
// default fhss parameters for this device
|
||||
uint8_t fhss_uc_dwell_interval;
|
||||
uint8_t fhss_bc_dwell_interval;
|
||||
|
@ -118,7 +119,9 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8
|
|||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur);
|
||||
void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64);
|
||||
|
||||
#define ws_info(cur) ((cur)->ws_info)
|
||||
#else
|
||||
|
@ -126,8 +129,9 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur);
|
|||
#define ws_common_seconds_timer(cur, seconds)
|
||||
#define ws_common_neighbor_update(cur, ll_address) ((void) 0)
|
||||
#define ws_common_aro_failure(cur, ll_address)
|
||||
#define ws_common_neighbor_remove(cur, ll_address)
|
||||
#define ws_common_fast_timer(cur, ticks) ((void) 0)
|
||||
#define ws_common_allow_child_registration(cur) (false)
|
||||
#define ws_common_allow_child_registration(cur, eui64) (false)
|
||||
|
||||
|
||||
#endif //HAVE_WS
|
||||
|
|
|
@ -186,6 +186,7 @@ typedef struct ws_bs_ie {
|
|||
#define WS_FAN_VERSION_1_0 1
|
||||
|
||||
#define WS_NEIGHBOR_LINK_TIMEOUT 2200
|
||||
#define WS_NEIGHBOR_NOT_TRUSTED_LINK_TIMEOUT 60
|
||||
#define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2
|
||||
|
||||
#define WS_NEIGBOR_ETX_SAMPLE_MAX 3
|
||||
|
@ -198,6 +199,18 @@ typedef struct ws_bs_ie {
|
|||
|
||||
#define WS_NUD_RANDOM_COMPARE (WS_NUD_RAND_PROBABILITY*WS_NUD_RANDOM_SAMPLE_LENGTH) / 100
|
||||
|
||||
#define WS_ETX_MIN_SAMPLE_COUNT 4
|
||||
|
||||
#define WS_ETX_MAX_UPDATE 1024
|
||||
|
||||
#define WS_ETX_MIN_WAIT_TIME 60
|
||||
|
||||
/**
|
||||
* Wi-sun spesific non-preferred prefix policy label
|
||||
*/
|
||||
|
||||
#define WS_NON_PREFFRED_LABEL 36
|
||||
|
||||
/*
|
||||
* Threshold (referenced to DEVICE_MIN_SENS) above which a neighbor node may be considered for inclusion into candidate parent set
|
||||
*/
|
||||
|
@ -226,6 +239,11 @@ typedef struct ws_bs_ie {
|
|||
*/
|
||||
#define WS_TACK_MAX_MS 5
|
||||
|
||||
// With FHSS we need to check CCA twice on TX channel
|
||||
#define WS_NUMBER_OF_CSMA_PERIODS 2
|
||||
// Interval between two CCA checks
|
||||
#define WS_CSMA_MULTI_CCA_INTERVAL 1000
|
||||
|
||||
/* Default FHSS timing information
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define WS_RPL_DIO_IMIN 14
|
||||
#define WS_RPL_DIO_DOUBLING 3
|
||||
#define WS_RPL_DIO_IMIN 15
|
||||
#define WS_RPL_DIO_DOUBLING 2
|
||||
#define WS_RPL_DIO_REDUNDANCY 0
|
||||
|
||||
|
||||
|
|
|
@ -197,12 +197,15 @@ int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr,
|
|||
}
|
||||
msdu_entry->data_ptr = data;
|
||||
msdu_entry->buffer = buffer;
|
||||
msdu_entry->handle = eapol_pdu_data->msdu_handle++;
|
||||
msdu_entry->handle = eapol_pdu_data->msdu_handle;
|
||||
ns_list_add_to_start(&eapol_pdu_data->msdu_list, msdu_entry);
|
||||
|
||||
memcpy(data_request.DstAddr, eui_64, 8);
|
||||
data_request.msdu = data;
|
||||
data_request.msduLength = size;
|
||||
data_request.msduHandle = eapol_pdu_data->msdu_handle;
|
||||
|
||||
eapol_pdu_data->msdu_handle++;
|
||||
|
||||
eapol_pdu_data->mpx_api->mpx_data_request(eapol_pdu_data->mpx_api, &data_request, eapol_pdu_data->mpx_user_id);
|
||||
return 0;
|
||||
|
|
|
@ -181,5 +181,12 @@ int ws_test_gtk_time_settings_set(int8_t interface_id, uint8_t revocat_lifetime_
|
|||
return -1;
|
||||
}
|
||||
|
||||
#endif // no HAVE_WS
|
||||
int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4])
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) gtk;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // no HAVE_WS
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include "6LoWPAN/ws/ws_llc.h"
|
||||
#include "6LoWPAN/ws/ws_mpx_header.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "Security/PANA/pana_eap_header.h"
|
||||
#include "Security/eapol/eapol_helper.h"
|
||||
#include "Service_Libs/etx/etx.h"
|
||||
#include "fhss_ws_extension.h"
|
||||
|
||||
|
@ -511,9 +513,12 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
|
|||
mac_payload_IE_t ws_wp_nested;
|
||||
ws_us_ie_t us_ie;
|
||||
bool us_ie_inline = false;
|
||||
bool bs_ie_inline = false;
|
||||
ws_wp_nested.id = WS_WP_NESTED_IE;
|
||||
ws_bs_ie_t ws_bs_ie;
|
||||
if (mac_ie_payload_discover(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_wp_nested) > 2) {
|
||||
us_ie_inline = ws_wp_nested_us_read(ws_wp_nested.content_ptr, ws_wp_nested.length, &us_ie);
|
||||
bs_ie_inline = ws_wp_nested_bs_read(ws_wp_nested.content_ptr, ws_wp_nested.length, &ws_bs_ie);
|
||||
}
|
||||
|
||||
llc_neighbour_req_t neighbor_info;
|
||||
|
@ -534,7 +539,11 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
|
|||
if (ws_wh_ea_read(ie_ext->headerIeList, ie_ext->headerIeListLength, auth_eui64)) {
|
||||
ws_pae_controller_border_router_addr_write(base->interface_ptr, auth_eui64);
|
||||
}
|
||||
if (bs_ie_inline) {
|
||||
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Update BT if it is part of message
|
||||
ws_bt_ie_t ws_bt;
|
||||
|
@ -543,6 +552,8 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
|
|||
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
|
||||
// We have broadcast schedule set up set the broadcast parent schedule
|
||||
ns_fhss_ws_set_parent(interface->ws_info->fhss_api, neighbor_info.neighbor->mac64, &neighbor_info.ws_neighbor->fhss_data.bc_timing_info, false);
|
||||
} else if (ws_utt.message_type == WS_FT_EAPOL) {
|
||||
ws_bootstrap_eapol_parent_synch(interface, &neighbor_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,6 +628,37 @@ static uint16_t ws_mpx_header_size_get(llc_data_base_t *base, uint16_t user_id)
|
|||
return header_size;
|
||||
}
|
||||
|
||||
static bool ws_eapol_handshake_first_msg(uint8_t *pdu, uint16_t length, protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (!ws_eapol_relay_state_active(cur)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
eapol_pdu_t eapol_pdu;
|
||||
uint8_t kmp_type = *pdu++;
|
||||
length--;
|
||||
if (!eapol_parse_pdu_header(pdu, length, &eapol_pdu)) {
|
||||
return false;
|
||||
}
|
||||
if (eapol_pdu.packet_type == EAPOL_EAP_TYPE) {
|
||||
if (eapol_pdu.msg.eap.eap_code == EAP_REQ && eapol_pdu.msg.eap.type == EAP_IDENTITY) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
||||
uint8_t key_mask = eapol_pdu_key_mask_get(&eapol_pdu);
|
||||
if (kmp_type == 6 && key_mask == KEY_INFO_KEY_ACK) {
|
||||
//FWK first message validation
|
||||
return true;
|
||||
} else if (kmp_type == 7 && key_mask == (KEY_INFO_KEY_ACK | KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME)) {
|
||||
//GWK first message validation
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id)
|
||||
{
|
||||
llc_data_base_t *base = ws_llc_discover_by_mpx(api);
|
||||
|
@ -646,11 +688,9 @@ static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data
|
|||
nested_wp_id.vp_ie = true;
|
||||
}
|
||||
} else if (user_id == MPX_KEY_MANAGEMENT_ENC_USER_ID) {
|
||||
|
||||
if (*data->msdu == 1) { //Only when KMP_ID is 1
|
||||
ie_header_mask.ea_ie = ws_eapol_relay_state_active(base->interface_ptr);
|
||||
ie_header_mask.bt_ie = ie_header_mask.ea_ie;
|
||||
}
|
||||
ie_header_mask.bt_ie = ws_eapol_relay_state_active(base->interface_ptr);
|
||||
ie_header_mask.ea_ie = ws_eapol_handshake_first_msg(data->msdu, data->msduLength, base->interface_ptr);
|
||||
nested_wp_id.bs_ie = ie_header_mask.ea_ie;
|
||||
|
||||
}
|
||||
|
||||
|
@ -735,6 +775,11 @@ static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data
|
|||
ptr = ws_wp_base_write(ptr, nested_ie_length);
|
||||
//Write unicast schedule
|
||||
ptr = ws_wp_nested_hopping_schedule_write(ptr, base->ie_params.hopping_schedule, true);
|
||||
|
||||
if (nested_wp_id.bs_ie) {
|
||||
//Write Broadcastcast schedule
|
||||
ptr = ws_wp_nested_hopping_schedule_write(ptr, base->ie_params.hopping_schedule, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -138,7 +138,6 @@ uint8_t ws_neighbor_class_rssi_from_dbm_calculate(int8_t dbm_heard)
|
|||
{
|
||||
if (DEVICE_MIN_SENS > dbm_heard) {
|
||||
// We are hearing packet with lower than min_sens dynamically learn the sensitivity
|
||||
tr_info("heard packet below min sensitivity");
|
||||
DEVICE_MIN_SENS = dbm_heard;
|
||||
}
|
||||
return dbm_heard - DEVICE_MIN_SENS;
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef struct ws_neighbor_class_entry {
|
|||
bool candidate_parent: 1;
|
||||
bool broadcast_timing_info_stored: 1;
|
||||
bool broadcast_shedule_info_stored: 1;
|
||||
bool synch_done : 1;
|
||||
} ws_neighbor_class_entry_t;
|
||||
|
||||
/**
|
||||
|
@ -147,7 +148,7 @@ uint8_t ws_neighbor_class_rssi_from_dbm_calculate(int8_t dbm_heard);
|
|||
*
|
||||
*/
|
||||
#define ws_neighbor_class_rsl_in_get(ws_neighbour) (ws_neighbour->rsl_in >> WS_RSL_SCALING)
|
||||
#define ws_neighbor_class_rsl_out_get(ws_neighbour) (ws_neighbour->rsl_in >> WS_RSL_SCALING)
|
||||
#define ws_neighbor_class_rsl_out_get(ws_neighbour) (ws_neighbour->rsl_out >> WS_RSL_SCALING)
|
||||
|
||||
/**
|
||||
* ws_neighbor_class_neighbor_broadcast_schedule_set a function for update neighbor broadcast shedule information
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include <randLIB.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
|
@ -39,6 +40,7 @@
|
|||
#include "Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h"
|
||||
#include "Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "6LoWPAN/ws/ws_pae_timers.h"
|
||||
#include "6LoWPAN/ws/ws_pae_auth.h"
|
||||
#include "6LoWPAN/ws/ws_pae_lib.h"
|
||||
|
||||
|
@ -54,23 +56,43 @@
|
|||
// Wait for for supplicant to indicate activity (e.g. to send a message)
|
||||
#define WAIT_FOR_AUTHENTICATION_TICKS 5 * 60 * 10 // 5 minutes
|
||||
|
||||
// Maximum number of simultaneous EAP-TLS negotiations
|
||||
#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS 3
|
||||
|
||||
/* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how
|
||||
long to wait for previous negotiation to complete */
|
||||
#define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds
|
||||
|
||||
typedef struct {
|
||||
ns_list_link_t link; /**< Link */
|
||||
kmp_service_t *kmp_service; /**< KMP service */
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */
|
||||
ws_pae_auth_gtk_hash_set *hash_set; /**< GTK hash set callback */
|
||||
ws_pae_auth_nw_key_insert *nw_key_insert; /**< Key insert callback */
|
||||
ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
|
||||
supp_list_t active_supp_list; /**< List of active supplicants */
|
||||
supp_list_t inactive_supp_list; /**< List of inactive supplicants */
|
||||
arm_event_storage_t *timer; /**< Timer */
|
||||
sec_prot_gtk_keys_t *gtks; /**< GTKs */
|
||||
sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */
|
||||
const sec_prot_certs_t *certs; /**< Certificates */
|
||||
bool timer_running; /**< Timer is running */
|
||||
timer_settings_t *timer_settings; /**< Timer settings */
|
||||
uint16_t slow_timer_seconds; /**< Slow timer seconds */
|
||||
bool timer_running : 1; /**< Timer is running */
|
||||
bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */
|
||||
bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */
|
||||
} pae_auth_t;
|
||||
|
||||
static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth);
|
||||
static int8_t ws_pae_auth_active_gtk_set(pae_auth_t *pae_auth, uint8_t index);
|
||||
static int8_t ws_pae_auth_network_key_index_set(pae_auth_t *pae_auth, uint8_t index);
|
||||
static void ws_pae_auth_free(pae_auth_t *pae_auth);
|
||||
static pae_auth_t *ws_pae_auth_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
static pae_auth_t *ws_pae_auth_by_kmp_service_get(kmp_service_t *service);
|
||||
static int8_t ws_pae_auth_event_send(kmp_service_t *service, void *data);
|
||||
static void ws_pae_auth_tasklet_handler(arm_event_s *event);
|
||||
static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth);
|
||||
static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth);
|
||||
static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp);
|
||||
static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp);
|
||||
static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth);
|
||||
|
@ -82,13 +104,15 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
|
|||
static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result);
|
||||
static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr);
|
||||
static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
||||
static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry);
|
||||
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry);
|
||||
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp);
|
||||
|
||||
static int8_t tasklet_id = -1;
|
||||
static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link);
|
||||
|
||||
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs)
|
||||
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, timer_settings_t *timer_settings)
|
||||
{
|
||||
if (!interface_ptr || !gtks || !certs) {
|
||||
return -1;
|
||||
|
@ -108,8 +132,17 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
|||
ws_pae_lib_supp_list_init(&pae_auth->inactive_supp_list);
|
||||
pae_auth->timer = NULL;
|
||||
|
||||
pae_auth->hash_set = NULL;
|
||||
pae_auth->nw_key_insert = NULL;
|
||||
pae_auth->nw_key_index_set = NULL;
|
||||
|
||||
pae_auth->gtks = gtks;
|
||||
pae_auth->next_gtks = next_gtks;
|
||||
pae_auth->certs = certs;
|
||||
pae_auth->timer_settings = timer_settings;
|
||||
pae_auth->slow_timer_seconds = 0;
|
||||
pae_auth->gtk_new_inst_req_exp = false;
|
||||
pae_auth->gtk_new_act_time_exp = false;
|
||||
|
||||
pae_auth->kmp_service = kmp_service_create();
|
||||
if (!pae_auth->kmp_service) {
|
||||
|
@ -205,6 +238,212 @@ int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
pae_auth->hash_set = hash_set;
|
||||
pae_auth->nw_key_insert = nw_key_insert;
|
||||
pae_auth->nw_key_index_set = nw_key_index_set;
|
||||
}
|
||||
|
||||
void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Checks if there is predefined active key
|
||||
int8_t index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks);
|
||||
if (index < 0) {
|
||||
// If there is no key, inserts a new one
|
||||
ws_pae_auth_gtk_key_insert(pae_auth);
|
||||
index = sec_prot_keys_gtk_install_order_first_index_get(pae_auth->gtks);
|
||||
ws_pae_auth_active_gtk_set(pae_auth, index);
|
||||
} else {
|
||||
ws_pae_auth_active_gtk_set(pae_auth, index);
|
||||
}
|
||||
|
||||
// Inserts keys and updates GTK hash on stack
|
||||
ws_pae_auth_network_keys_from_gtks_set(pae_auth);
|
||||
|
||||
// Sets active key index
|
||||
ws_pae_auth_network_key_index_set(pae_auth, index);
|
||||
}
|
||||
|
||||
void ws_pae_auth_gtks_updated(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
ws_pae_auth_network_keys_from_gtks_set(pae_auth);
|
||||
}
|
||||
|
||||
int8_t ws_pae_auth_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_auth_active_gtk_set(pae_auth, index);
|
||||
ws_pae_auth_network_key_index_set(pae_auth, index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Checks if supplicant is active
|
||||
supp_entry_t *supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, eui_64);
|
||||
|
||||
if (supp) {
|
||||
// Deletes keys and marks as revoked
|
||||
sec_prot_keys_pmk_delete(&supp->sec_keys);
|
||||
sec_prot_keys_ptk_delete(&supp->sec_keys);
|
||||
supp->access_revoked = true;
|
||||
tr_info("Access revoked; keys removed, eui-64: %s", trace_array(kmp_address_eui_64_get(supp->addr), 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Checks if supplicant is inactive
|
||||
supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->inactive_supp_list, eui_64);
|
||||
if (supp) {
|
||||
// Deletes supplicant
|
||||
tr_info("Access revoked; deleted, eui-64: %s", trace_array(kmp_address_eui_64_get(supp->addr), 8));
|
||||
ws_pae_lib_supp_list_remove(&pae_auth->inactive_supp_list, supp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Gets active GTK
|
||||
int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks);
|
||||
|
||||
if (active_index >= 0) {
|
||||
// As default removes other keys than active
|
||||
int8_t not_removed_index = active_index;
|
||||
|
||||
uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->timer_settings);
|
||||
|
||||
uint32_t active_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, active_index);
|
||||
|
||||
// If active GTK lifetime is larger than revocation lifetime decrements active GTK lifetime
|
||||
if (active_lifetime > revocation_lifetime) {
|
||||
sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, active_index, active_lifetime - revocation_lifetime);
|
||||
tr_info("Access revocation start, GTK active index: %i, revoked lifetime: %"PRIu32"", active_index, revocation_lifetime);
|
||||
} else {
|
||||
// Otherwise decrements lifetime of the GTK to be installed after the active one
|
||||
int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks);
|
||||
if (second_index >= 0) {
|
||||
// Second GTK revocation lifetime is the active GTK lifetime added with revocation time
|
||||
uint32_t second_revocation_lifetime = active_lifetime + revocation_lifetime;
|
||||
|
||||
uint32_t second_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, second_index);
|
||||
if (second_lifetime > second_revocation_lifetime) {
|
||||
sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, second_index, second_lifetime - second_revocation_lifetime);
|
||||
tr_info("Access revocation start, GTK second active index: %i, revoked lifetime: %"PRIu32"", second_index, second_revocation_lifetime);
|
||||
}
|
||||
// Removes other keys than active and GTK to be installed next
|
||||
not_removed_index = second_index;
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes other GTKs
|
||||
int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks);
|
||||
while (last_index >= 0 && last_index != not_removed_index) {
|
||||
tr_info("Access revocation GTK clear index: %i", last_index);
|
||||
sec_prot_keys_gtk_clear(pae_auth->gtks, last_index);
|
||||
last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds new GTK
|
||||
ws_pae_auth_gtk_key_insert(pae_auth);
|
||||
ws_pae_auth_network_keys_from_gtks_set(pae_auth);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth)
|
||||
{
|
||||
// Authenticator keys are always fresh
|
||||
sec_prot_keys_gtk_status_all_fresh_set(pae_auth->gtks);
|
||||
|
||||
if (pae_auth->hash_set) {
|
||||
uint8_t gtk_hash[32];
|
||||
sec_prot_keys_gtks_hash_generate(pae_auth->gtks, gtk_hash);
|
||||
pae_auth->hash_set(pae_auth->interface_ptr, gtk_hash);
|
||||
}
|
||||
|
||||
if (pae_auth->nw_key_insert) {
|
||||
pae_auth->nw_key_insert(pae_auth->interface_ptr, pae_auth->gtks);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_active_gtk_set(pae_auth_t *pae_auth, uint8_t index)
|
||||
{
|
||||
return sec_prot_keys_gtk_status_active_set(pae_auth->gtks, index);
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_gtk_clear(pae_auth_t *pae_auth, uint8_t index)
|
||||
{
|
||||
return sec_prot_keys_gtk_clear(pae_auth->gtks, index);
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_network_key_index_set(pae_auth_t *pae_auth, uint8_t index)
|
||||
{
|
||||
if (pae_auth->nw_key_index_set) {
|
||||
pae_auth->nw_key_index_set(pae_auth->interface_ptr, index);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_pae_auth_free(pae_auth_t *pae_auth)
|
||||
{
|
||||
if (!pae_auth) {
|
||||
|
@ -287,7 +526,7 @@ static void ws_pae_auth_tasklet_handler(arm_event_s *event)
|
|||
}
|
||||
}
|
||||
|
||||
void ws_pae_auth_timer(uint16_t ticks)
|
||||
void ws_pae_auth_fast_timer(uint16_t ticks)
|
||||
{
|
||||
ns_list_foreach(pae_auth_t, pae_auth, &pae_auth_list) {
|
||||
if (!ws_pae_auth_timer_running(pae_auth)) {
|
||||
|
@ -302,6 +541,111 @@ void ws_pae_auth_timer(uint16_t ticks)
|
|||
}
|
||||
}
|
||||
|
||||
void ws_pae_auth_slow_timer(uint16_t seconds)
|
||||
{
|
||||
ns_list_foreach(pae_auth_t, pae_auth, &pae_auth_list) {
|
||||
|
||||
// Gets index of currently active GTK
|
||||
int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks);
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (!sec_prot_keys_gtk_is_set(pae_auth->gtks, i)) {
|
||||
continue;
|
||||
}
|
||||
uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, i, seconds);
|
||||
if (active_index == i) {
|
||||
if (!pae_auth->gtk_new_inst_req_exp) {
|
||||
pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->timer_settings, timer_seconds);
|
||||
if (pae_auth->gtk_new_inst_req_exp) {
|
||||
int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks);
|
||||
if (second_index < 0) {
|
||||
tr_info("GTK new install required active index: %i, time: %"PRIu32", system time: %"PRIu32"", active_index, timer_seconds, protocol_core_monotonic_time / 10);
|
||||
ws_pae_auth_gtk_key_insert(pae_auth);
|
||||
ws_pae_auth_network_keys_from_gtks_set(pae_auth);
|
||||
} else {
|
||||
tr_info("GTK new install already done; second index: %i, time: %"PRIu32", system time: %"PRIu32"", second_index, timer_seconds, protocol_core_monotonic_time / 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pae_auth->gtk_new_act_time_exp) {
|
||||
pae_auth->gtk_new_act_time_exp = ws_pae_timers_gtk_new_activation_time(pae_auth->timer_settings, timer_seconds);
|
||||
if (pae_auth->gtk_new_act_time_exp) {
|
||||
int8_t new_active_index = ws_pae_auth_new_gtk_activate(pae_auth);
|
||||
tr_info("GTK new activation time active index: %i, time: %"PRIu32", new index: %i, system time: %"PRIu32"", active_index, timer_seconds, new_active_index, protocol_core_monotonic_time / 10);
|
||||
if (new_active_index >= 0) {
|
||||
ws_pae_auth_network_key_index_set(pae_auth, new_active_index);
|
||||
}
|
||||
pae_auth->gtk_new_inst_req_exp = false;
|
||||
pae_auth->gtk_new_act_time_exp = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timer_seconds == 0) {
|
||||
tr_info("GTK expired index: %i, system time: %"PRIu32"", i, protocol_core_monotonic_time / 10);
|
||||
ws_pae_auth_gtk_clear(pae_auth, i);
|
||||
ws_pae_auth_network_keys_from_gtks_set(pae_auth);
|
||||
}
|
||||
}
|
||||
|
||||
pae_auth->slow_timer_seconds += seconds;
|
||||
if (pae_auth->slow_timer_seconds > 60) {
|
||||
ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, pae_auth->timer_settings, pae_auth->slow_timer_seconds);
|
||||
ws_pae_lib_supp_list_slow_timer_update(&pae_auth->inactive_supp_list, pae_auth->timer_settings, pae_auth->slow_timer_seconds);
|
||||
pae_auth->slow_timer_seconds = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth)
|
||||
{
|
||||
// Gets index to install the key
|
||||
uint8_t install_index = sec_prot_keys_gtk_install_index_get(pae_auth->gtks);
|
||||
|
||||
// Key to install
|
||||
uint8_t gtk_value[GTK_LEN];
|
||||
|
||||
// Checks if next GTK values are set and gets first GTK to install
|
||||
int8_t next_gtk_index = sec_prot_keys_gtk_install_order_first_index_get(pae_auth->next_gtks);
|
||||
if (next_gtk_index >= 0) {
|
||||
// Gets GTK value
|
||||
uint8_t *gtk = sec_prot_keys_gtk_get(pae_auth->next_gtks, next_gtk_index);
|
||||
memcpy(gtk_value, gtk, GTK_LEN);
|
||||
// Sets same key back to next GTKs but as the last key to be installed
|
||||
sec_prot_keys_gtk_clear(pae_auth->next_gtks, next_gtk_index);
|
||||
sec_prot_keys_gtk_set(pae_auth->next_gtks, next_gtk_index, gtk_value, 0);
|
||||
} else {
|
||||
randLIB_get_n_bytes_random(gtk_value, GTK_LEN);
|
||||
}
|
||||
|
||||
// Gets latest installed key lifetime and adds GTK expire offset to it
|
||||
uint32_t lifetime = pae_auth->timer_settings->gtk_expire_offset;
|
||||
int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks);
|
||||
if (last_index >= 0) {
|
||||
lifetime += sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, last_index);
|
||||
}
|
||||
|
||||
// Installs the new key
|
||||
sec_prot_keys_gtk_clear(pae_auth->gtks, install_index);
|
||||
sec_prot_keys_gtk_set(pae_auth->gtks, install_index, gtk_value, lifetime);
|
||||
|
||||
// Authenticator keys are always fresh
|
||||
sec_prot_keys_gtk_status_all_fresh_set(pae_auth->gtks);
|
||||
|
||||
tr_info("GTK install new index: %i, lifetime: %"PRIu32" system time: %"PRIu32"", install_index, lifetime, protocol_core_monotonic_time / 10);
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth)
|
||||
{
|
||||
int8_t new_active_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks);
|
||||
if (new_active_index >= 0) {
|
||||
ws_pae_auth_active_gtk_set(pae_auth, new_active_index);
|
||||
}
|
||||
|
||||
return new_active_index;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp)
|
||||
{
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
|
@ -363,19 +707,16 @@ static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth)
|
|||
|
||||
static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr)
|
||||
{
|
||||
(void) service;
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Get own EUI-64
|
||||
link_layer_address_s mac_params;
|
||||
if (arm_nwk_mac_address_read(pae_auth->interface_ptr->id, &mac_params) >= 0) {
|
||||
kmp_address_eui_64_set(local_addr, mac_params.mac_long);
|
||||
}
|
||||
#endif
|
||||
|
||||
// For now fixed since not yet support for EA-IE in supplicants
|
||||
uint8_t addr[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
kmp_address_eui_64_set(local_addr, addr);
|
||||
|
||||
// Get supplicant address
|
||||
supp_entry_t *entry = kmp_api_data_get(kmp);
|
||||
|
@ -422,6 +763,8 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
|
|||
return 0;
|
||||
}
|
||||
sec_prot_keys_init(&supp_entry->sec_keys, pae_auth->gtks, pae_auth->certs);
|
||||
// Fixes the address of the supplicant to keys
|
||||
sec_prot_keys_ptk_eui_64_write(&supp_entry->sec_keys, kmp_address_eui_64_get(addr));
|
||||
} else {
|
||||
// Updates relay address
|
||||
kmp_address_copy(supp_entry->addr, addr);
|
||||
|
@ -498,64 +841,116 @@ static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
|
|||
// Should not be possible
|
||||
return;
|
||||
}
|
||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
// Should not be possible
|
||||
return;
|
||||
}
|
||||
|
||||
// Gets type
|
||||
kmp_type_e type = kmp_api_type_get(kmp);
|
||||
ws_pae_auth_next_kmp_trigger(pae_auth, supp_entry);
|
||||
}
|
||||
|
||||
if (type > IEEE_802_1X_INITIAL_KEY) {
|
||||
// For EAPOL-key, start EAP-TLS towards supplicant
|
||||
type = IEEE_802_1X_MKA;
|
||||
tr_debug("PAE start EAP-TLS, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
} else if (type == IEEE_802_1X_MKA) {
|
||||
// After EAP-TLS start 4WH towards supplicant
|
||||
type = IEEE_802_11_4WH;
|
||||
// Insert GTK0
|
||||
sec_prot_keys_gtk_insert_index_set(supp_entry->sec_keys.gtks, 0);
|
||||
tr_debug("PAE start 4WH, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
} else if (type == IEEE_802_11_4WH) {
|
||||
// After 4WH start GKH towards supplicant
|
||||
type = IEEE_802_11_GKH;
|
||||
// Insert GTK1
|
||||
sec_prot_keys_gtk_insert_index_set(supp_entry->sec_keys.gtks, 1);
|
||||
tr_debug("PAE start GKH, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
} else if (type == IEEE_802_11_GKH) {
|
||||
tr_debug("PAE authenticated, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
// After GKH end
|
||||
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry)
|
||||
{
|
||||
// Disables KMP retry timer
|
||||
supp_entry->retry_ticks = 0;
|
||||
|
||||
// Get next protocol based on what keys supplicant has
|
||||
kmp_type_e next_type = ws_pae_auth_next_protocol_get(supp_entry);
|
||||
|
||||
if (next_type == KMP_TYPE_NONE) {
|
||||
// All done
|
||||
return;
|
||||
}
|
||||
|
||||
// Increases waiting time for supplicant authentication
|
||||
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||
|
||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
if (next_type == IEEE_802_1X_MKA) {
|
||||
/* For EAP-TLS, limits the number of ongoing negotiations. If limit
|
||||
is reached, authenticator does not initiate EAP-TLS right away.
|
||||
If previous EAP-TLS negotiation completes before negotiation
|
||||
trigger timeout, authenticator initiates EAP-TLS towards
|
||||
supplicant. Otherwise supplicant must re-send initial EAPOL-Key
|
||||
to try again using its trickle schedule */
|
||||
uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, IEEE_802_1X_MKA);
|
||||
if (ongoing_eap_tls_cnt >= MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS) {
|
||||
supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT;
|
||||
tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new instance
|
||||
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, type, supp_entry);
|
||||
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, supp_entry);
|
||||
if (!new_kmp) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For EAP-TLS create also TLS in addition to EAP-TLS
|
||||
if (type == IEEE_802_1X_MKA) {
|
||||
if (next_type == IEEE_802_1X_MKA) {
|
||||
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, TLS_PROT) != NULL) {
|
||||
// TLS already exists, wait for it to be deleted
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
}
|
||||
// Create TLS instance */
|
||||
if (ws_pae_auth_kmp_create_and_start(service, TLS_PROT, supp_entry) == NULL) {
|
||||
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry) == NULL) {
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
kmp_api_create_request(new_kmp, type, supp_entry->addr, &supp_entry->sec_keys);
|
||||
kmp_api_create_request(new_kmp, next_type, supp_entry->addr, &supp_entry->sec_keys);
|
||||
}
|
||||
|
||||
static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry)
|
||||
{
|
||||
kmp_type_e next_type = KMP_TYPE_NONE;
|
||||
sec_prot_keys_t *sec_keys = &supp_entry->sec_keys;
|
||||
|
||||
// Supplicant has indicated that PMK is not valid
|
||||
if (sec_keys->pmk_mismatch) {
|
||||
sec_keys->ptk_mismatch = true;
|
||||
// start EAP-TLS towards supplicant
|
||||
next_type = IEEE_802_1X_MKA;
|
||||
tr_info("PAE start EAP-TLS, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
} else if (sec_keys->ptk_mismatch) {
|
||||
// start 4WH towards supplicant
|
||||
next_type = IEEE_802_11_4WH;
|
||||
tr_info("PAE start 4WH, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
}
|
||||
|
||||
int8_t gtk_index = -1;
|
||||
if (next_type != IEEE_802_1X_MKA) {
|
||||
// Checks if GTK needs to be inserted
|
||||
gtk_index = sec_prot_keys_gtk_insert_index_from_gtkl_get(sec_keys);
|
||||
|
||||
// For 4WH insert always a key, in case no other then active
|
||||
if (next_type == IEEE_802_11_4WH && gtk_index < 0) {
|
||||
gtk_index = sec_prot_keys_gtk_status_active_get(sec_keys->gtks);
|
||||
}
|
||||
}
|
||||
|
||||
if (gtk_index >= 0) {
|
||||
if (next_type == KMP_TYPE_NONE && gtk_index >= 0) {
|
||||
// Update just GTK
|
||||
next_type = IEEE_802_11_GKH;
|
||||
tr_info("PAE start GKH, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
}
|
||||
|
||||
tr_info("PAE update GTK index: %i, eui-64: %s", gtk_index, trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
}
|
||||
|
||||
if (next_type == KMP_TYPE_NONE) {
|
||||
tr_info("PAE authenticated, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
}
|
||||
|
||||
return next_type;
|
||||
}
|
||||
|
||||
|
||||
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry)
|
||||
{
|
||||
// Create KMP instance for new authentication
|
||||
|
@ -594,8 +989,25 @@ static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp)
|
|||
return;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = NULL;
|
||||
supp_entry_t *retry_supp = NULL;
|
||||
// When EAP-TLS completes check if there are other supplicants that have requested it lately
|
||||
if (kmp_api_type_get(kmp) == IEEE_802_1X_MKA) {
|
||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||
pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (pae_auth) {
|
||||
retry_supp = ws_pae_lib_supp_list_entry_retry_timer_get(&pae_auth->active_supp_list);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete KMP
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp);
|
||||
|
||||
if (retry_supp) {
|
||||
tr_info("PAE next KMP trigger, eui-64: %s", trace_array(kmp_address_eui_64_get(retry_supp->addr), 8));
|
||||
ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* HAVE_PAE_AUTH */
|
||||
|
|
|
@ -44,13 +44,15 @@
|
|||
* \param remote_addr remote address
|
||||
* \param remote_port remote port
|
||||
* \param gtks group keys
|
||||
* \param next_gtks next group keys to be used
|
||||
* \param cert_chain certificate chain
|
||||
* \param timer_settings timer settings
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs);
|
||||
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, timer_settings_t *timer_settings);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_addresses_set set relay addresses
|
||||
|
@ -78,19 +80,126 @@ int8_t ws_pae_auth_addresses_set(protocol_interface_info_entry_t *interface_ptr,
|
|||
int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_timer PAE authenticator timer call
|
||||
* ws_pae_auth_fast_timer PAE authenticator fast timer call
|
||||
*
|
||||
* \param ticks elapsed ticks
|
||||
*
|
||||
*/
|
||||
void ws_pae_auth_timer(uint16_t ticks);
|
||||
void ws_pae_auth_fast_timer(uint16_t ticks);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_slow_timer PAE authenticator slow call
|
||||
*
|
||||
* \param seconds elapsed seconds
|
||||
*
|
||||
*/
|
||||
void ws_pae_auth_slow_timer(uint16_t seconds);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_start start PAE authenticator
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
*/
|
||||
void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_gtks_updated indicates that GTKs has been updated
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
*/
|
||||
void ws_pae_auth_gtks_updated(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_gtks_updated indicates that key index has been updated
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param index key index
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_auth_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_node_keys_remove removes nodes keys
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param eui64 node's EUI-64
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui64);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_node_access_revoke_start start node's access revoke
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_gtk_hash_set GTK hash set callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtkhash GTK hash, 32 bytes
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_auth_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_nw_key_insert network key insert callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtks group keys
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
typedef int8_t ws_pae_auth_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_nw_key_index_set network send key index set callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param index network send key index
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_auth_nw_key_index_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_cb_register register PAE authenticator callbacks
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param hash_set GTK hash set callback
|
||||
* \param nw_key_insert network key index callback
|
||||
* \param nw_key_index_set network send key index callback
|
||||
*
|
||||
*/
|
||||
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_pae_auth_init(interface_ptr, gtks, certs) 1
|
||||
#define ws_pae_auth_init(interface_ptr, gtks, next_gtks, certs, timer_settings) 1
|
||||
#define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1
|
||||
#define ws_pae_auth_delete NULL
|
||||
#define ws_pae_auth_timer NULL
|
||||
#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set) {(void) hash_set;}
|
||||
#define ws_pae_auth_start(interface_ptr)
|
||||
#define ws_pae_auth_gtks_updated NULL
|
||||
#define ws_pae_auth_nw_key_index_update NULL
|
||||
#define ws_pae_auth_node_keys_remove(interface_ptr, eui64) -1
|
||||
#define ws_pae_auth_node_access_revoke_start(interface_ptr)
|
||||
#define ws_pae_auth_fast_timer NULL
|
||||
#define ws_pae_auth_slow_timer NULL
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -28,8 +28,10 @@
|
|||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "Security/protocols/sec_prot_certs.h"
|
||||
#include "Security/protocols/sec_prot_keys.h"
|
||||
#include "6LoWPAN/ws/ws_pae_timers.h"
|
||||
#include "6LoWPAN/ws/ws_pae_supp.h"
|
||||
#include "6LoWPAN/ws/ws_pae_auth.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
|
@ -39,7 +41,15 @@ typedef int8_t ws_pae_delete(protocol_interface_info_entry_t *interface_ptr);
|
|||
typedef void ws_pae_timer(uint16_t ticks);
|
||||
typedef int8_t ws_pae_br_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
typedef int8_t ws_pae_br_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
|
||||
typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr);
|
||||
typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||
typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
typedef struct {
|
||||
uint8_t hash[8]; /**< GTK hash for the key */
|
||||
bool installed : 1; /**< Key has been installed on MAC */
|
||||
bool fresh : 1; /**< Key is fresh i.e. not used on sending */
|
||||
} nw_key_t;
|
||||
|
||||
typedef struct {
|
||||
ns_list_link_t link; /**< Link */
|
||||
|
@ -47,68 +57,94 @@ typedef struct {
|
|||
uint16_t target_pan_id; /**< EAPOL target PAN ID */
|
||||
uint8_t br_eui_64[8]; /**< Border router EUI-64 */
|
||||
sec_prot_gtk_keys_t gtks; /**< GTKs */
|
||||
sec_prot_gtk_keys_t next_gtks; /**< Next GTKs */
|
||||
int8_t gtk_index; /**< GTK index */
|
||||
uint8_t gtkhash[32]; /**< GTK hashes */
|
||||
sec_prot_certs_t certs; /**< Certificates */
|
||||
nw_key_t nw_key[4]; /**< Currently active network keys (on MAC) */
|
||||
char *network_name; /**< Network name for GAK generation */
|
||||
timer_settings_t timer_settings; /**< Timer settings */
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
|
||||
ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
|
||||
ws_pae_controller_key_insert *key_insert; /**< Key insert callback */
|
||||
ws_pae_controller_nw_key_set *nw_key_set; /**< Key set callback */
|
||||
ws_pae_controller_nw_key_clear *nw_key_clear; /**< Key clear callback */
|
||||
ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set; /**< Send key index set callback */
|
||||
ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set; /**< Frame counter set callback */
|
||||
ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */
|
||||
ws_pae_delete *pae_delete; /**< PAE delete callback */
|
||||
ws_pae_timer *pae_timer; /**< PAE timer callback */
|
||||
ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */
|
||||
ws_pae_timer *pae_slow_timer; /**< PAE slow timer callback */
|
||||
ws_pae_br_addr_write *pae_br_addr_write; /**< PAE Border router EUI-64 write callback */
|
||||
ws_pae_br_addr_read *pae_br_addr_read; /**< PAE Border router EUI-64 read callback */
|
||||
ws_pae_gtks_updated *pae_gtks_updated; /**< PAE GTKs updated */
|
||||
ws_pae_gtk_hash_update *pae_gtk_hash_update; /**< PAE GTK HASH update */
|
||||
ws_pae_nw_key_index_update *pae_nw_key_index_update; /**< PAE NW key index update */
|
||||
bool gtks_set : 1; /**< GTKs are set */
|
||||
bool gtkhash_set : 1; /**< GTK hashes are set */
|
||||
bool key_index_set : 1; /**< NW key index is set */
|
||||
} pae_controller_t;
|
||||
|
||||
static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks);
|
||||
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id);
|
||||
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
|
||||
static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key);
|
||||
static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index);
|
||||
static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name);
|
||||
static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
static void ws_pae_controller_data_init(pae_controller_t *controller);
|
||||
|
||||
static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
|
||||
|
||||
#if !defined(HAVE_PAE_SUPP) && !defined(HAVE_PAE_AUTH)
|
||||
|
||||
static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
uint8_t gtk[2][GTK_LEN];
|
||||
uint8_t gtk[GTK_LEN];
|
||||
|
||||
// Test data
|
||||
for (int i = 0; i < GTK_LEN; i++) {
|
||||
gtk[0][i] = 0xcf - i;
|
||||
gtk[1][i] = 0xef - i;
|
||||
gtk[i] = 0xcf - i;
|
||||
}
|
||||
|
||||
sec_prot_keys_gtk_set(gtks, 0, gtk[0]);
|
||||
sec_prot_keys_gtk_set(gtks, 1, gtk[1]);
|
||||
|
||||
sec_prot_keys_gtkl_set(gtks, 0xFF);
|
||||
|
||||
sec_prot_keys_gtk_insert_index_set(gtks, 0);
|
||||
sec_prot_keys_gtk_set(gtks, 0, gtk, GTK_DEFAULT_LIFETIME);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define ws_pae_controller_test_keys_set(gtks);
|
||||
|
||||
#endif
|
||||
|
||||
int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64) == PAE_SUPP_NOT_ENABLED) {
|
||||
// Already authenticated
|
||||
ws_pae_controller_test_keys_set(&controller->gtks);
|
||||
|
||||
uint8_t index;
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(&controller->gtks, &index);
|
||||
|
||||
controller->key_insert(controller->interface_ptr, index, gtk);
|
||||
#ifdef HAVE_PAE_SUPP
|
||||
// In case test keys are set uses those and does not initiate authentication
|
||||
if (controller->gtks_set) {
|
||||
if (sec_prot_keys_gtks_are_updated(&controller->gtks)) {
|
||||
ws_pae_controller_nw_key_check_and_insert(controller->interface_ptr, &controller->gtks);
|
||||
sec_prot_keys_gtks_updated_reset(&controller->gtks);
|
||||
}
|
||||
controller->auth_completed(interface_ptr, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////
|
||||
// For now fixed since not yet support for EA-IE
|
||||
const uint8_t addr[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
if (controller->pae_br_addr_write) {
|
||||
controller->pae_br_addr_write(interface_ptr, addr);
|
||||
if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64) < 0) {
|
||||
controller->auth_completed(interface_ptr, false);
|
||||
}
|
||||
////////////////
|
||||
|
||||
#else
|
||||
ws_pae_controller_test_keys_set(&controller->gtks);
|
||||
ws_pae_controller_nw_key_check_and_insert(interface_ptr, &controller->gtks);
|
||||
ws_pae_controller_nw_key_index_check_and_set(interface_ptr, 0);
|
||||
|
||||
controller->auth_completed(interface_ptr, true);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -127,21 +163,32 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PAE_AUTH
|
||||
if (sec_prot_keys_gtks_are_updated(&controller->gtks)) {
|
||||
ws_pae_auth_gtks_updated(interface_ptr);
|
||||
if (controller->gtk_index >= 0) {
|
||||
controller->pae_nw_key_index_update(interface_ptr, controller->gtk_index);
|
||||
}
|
||||
sec_prot_keys_gtks_updated_reset(&controller->gtks);
|
||||
}
|
||||
#else
|
||||
ws_pae_controller_test_keys_set(&controller->gtks);
|
||||
|
||||
uint8_t index;
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(&controller->gtks, &index);
|
||||
|
||||
controller->key_insert(controller->interface_ptr, index, gtk);
|
||||
ws_pae_controller_nw_key_check_and_insert(interface_ptr, &controller->gtks);
|
||||
ws_pae_controller_nw_key_index_check_and_set(interface_ptr, 0);
|
||||
#endif
|
||||
|
||||
if (ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set);
|
||||
|
||||
ws_pae_auth_start(interface_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_key_insert *key_insert)
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_pan_ver_increment *pan_ver_increment)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
|
@ -153,7 +200,11 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_
|
|||
}
|
||||
|
||||
controller->auth_completed = completed;
|
||||
controller->key_insert = key_insert;
|
||||
controller->nw_key_set = nw_key_set;
|
||||
controller->nw_key_clear = nw_key_clear;
|
||||
controller->nw_send_key_index_set = nw_send_key_index_set;
|
||||
controller->nw_frame_counter_set = nw_frame_counter_set;
|
||||
controller->pan_ver_increment = pan_ver_increment;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -189,6 +240,8 @@ int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_
|
|||
return -1;
|
||||
}
|
||||
|
||||
controller->network_name = network_name;
|
||||
|
||||
return ws_pae_supp_nw_info_set(interface_ptr, pan_id, network_name);
|
||||
}
|
||||
|
||||
|
@ -206,6 +259,202 @@ int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface
|
|||
return ws_pae_supp_nw_key_valid(interface_ptr);
|
||||
}
|
||||
|
||||
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
int8_t ret = -1;
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t gtkhash[GTK_ALL_HASHES_LEN];
|
||||
sec_prot_keys_gtks_hash_generate(gtks, gtkhash);
|
||||
|
||||
nw_key_t *nw_key = controller->nw_key;
|
||||
|
||||
// Delete old keys
|
||||
uint8_t *gtk_hash_ptr = gtkhash;
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
// If hash is not set for a key
|
||||
if (sec_prot_keys_gtk_hash_empty(gtk_hash_ptr)) {
|
||||
// Deletes the key if it is set
|
||||
if (!sec_prot_keys_gtk_hash_empty(nw_key[i].hash)) {
|
||||
tr_info("NW key remove: %i", i);
|
||||
controller->nw_key_clear(interface_ptr, i);
|
||||
nw_key[i].installed = false;
|
||||
}
|
||||
}
|
||||
gtk_hash_ptr += GTK_HASH_LEN;
|
||||
}
|
||||
|
||||
// Insert new keys
|
||||
gtk_hash_ptr = gtkhash;
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
// If hash is set for a key
|
||||
if (!sec_prot_keys_gtk_hash_empty(gtk_hash_ptr)) {
|
||||
int hash_matches = memcmp(gtk_hash_ptr, nw_key[i].hash, GTK_HASH_LEN);
|
||||
// If the hash does not match (not set or modified) or not installed
|
||||
if (hash_matches != 0 || !nw_key[i].installed) {
|
||||
|
||||
memcpy(nw_key[i].hash, gtk_hash_ptr, GTK_HASH_LEN);
|
||||
|
||||
nw_key[i].installed = true;
|
||||
if (hash_matches != 0) {
|
||||
nw_key[i].fresh = true;
|
||||
}
|
||||
|
||||
uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
|
||||
tr_info("NW key set: %i, hash: %s", i, trace_array(nw_key[i].hash, 8));
|
||||
uint8_t gak[GTK_LEN];
|
||||
if (ws_pae_controller_gak_from_gtk(gak, gtk, controller->network_name) >= 0) {
|
||||
controller->nw_key_set(interface_ptr, i, i, gak);
|
||||
ret = 0;
|
||||
} else {
|
||||
tr_error("GAK generation failed network name: %s", controller->network_name);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gtk_hash_ptr += GTK_HASH_LEN;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key)
|
||||
{
|
||||
memset(nw_key, 0, sizeof(nw_key_t));
|
||||
nw_key->installed = false;
|
||||
nw_key->fresh = false;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name)
|
||||
{
|
||||
#if defined(HAVE_PAE_SUPP) || defined(HAVE_PAE_AUTH)
|
||||
uint8_t network_name_len = strlen(network_name);
|
||||
if (network_name_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t input[network_name_len + GTK_LEN];
|
||||
memcpy(input, network_name, network_name_len);
|
||||
memcpy(input + network_name_len, gtk, GTK_LEN);
|
||||
|
||||
int8_t ret_val = 0;
|
||||
|
||||
mbedtls_sha256_context ctx;
|
||||
|
||||
mbedtls_sha256_init(&ctx);
|
||||
|
||||
if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
|
||||
ret_val = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mbedtls_sha256_update_ret(&ctx, input, network_name_len + GTK_LEN) != 0) {
|
||||
ret_val = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
uint8_t output[32];
|
||||
|
||||
if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
|
||||
ret_val = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(gak, &output[0], 16);
|
||||
|
||||
error:
|
||||
mbedtls_sha256_free(&ctx);
|
||||
|
||||
return ret_val;
|
||||
#else
|
||||
(void) network_name;
|
||||
memcpy(gak, gtk, 16);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (controller->pae_nw_key_index_update) {
|
||||
controller->pae_nw_key_index_update(interface_ptr, index);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ws_pae_controller_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
tr_info("NW keys remove");
|
||||
|
||||
nw_key_t *nw_key = controller->nw_key;
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
// Deletes the key if it is set
|
||||
if (!sec_prot_keys_gtk_hash_empty(nw_key[i].hash)) {
|
||||
tr_info("NW key remove: %i", i);
|
||||
controller->nw_key_clear(interface_ptr, i);
|
||||
nw_key[i].installed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller->nw_send_key_index_set) {
|
||||
tr_info("NW send key index set: %i", index + 1);
|
||||
controller->nw_send_key_index_set(interface_ptr, index);
|
||||
controller->nw_frame_counter_set(interface_ptr, 0);
|
||||
}
|
||||
|
||||
// Do not update PAN version for initial key index set
|
||||
if (controller->key_index_set) {
|
||||
if (controller->pan_ver_increment) {
|
||||
controller->pan_ver_increment(interface_ptr);
|
||||
}
|
||||
} else {
|
||||
controller->key_index_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(cur);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller->nw_send_key_index_set) {
|
||||
controller->nw_send_key_index_set(controller->interface_ptr, index);
|
||||
|
||||
// If index has changed and the key for the index is fresh reset frame counter
|
||||
if (controller->gtk_index != index && controller->nw_key[index].fresh) {
|
||||
controller->nw_frame_counter_set(cur, 0);
|
||||
}
|
||||
|
||||
controller->gtk_index = index;
|
||||
controller->nw_key[index].fresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
|
@ -221,75 +470,97 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memset(controller->target_eui_64, 0, 8);
|
||||
memset(controller->br_eui_64, 0, 8);
|
||||
controller->interface_ptr = interface_ptr;
|
||||
controller->auth_completed = NULL;
|
||||
controller->key_insert = NULL;
|
||||
controller->pae_delete = NULL;
|
||||
controller->pae_timer = NULL;
|
||||
controller->pae_br_addr_write = NULL;
|
||||
controller->pae_br_addr_read = NULL;
|
||||
controller->nw_key_set = NULL;
|
||||
controller->nw_key_clear = NULL;
|
||||
controller->nw_send_key_index_set = NULL;
|
||||
controller->nw_frame_counter_set = NULL;
|
||||
controller->pan_ver_increment = NULL;
|
||||
|
||||
sec_prot_keys_gtks_init(&controller->gtks);
|
||||
sec_prot_certs_init(&controller->certs);
|
||||
ws_pae_controller_data_init(controller);
|
||||
|
||||
ns_list_add_to_end(&pae_controller_list, controller);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_pae_controller_data_init(pae_controller_t *controller)
|
||||
{
|
||||
memset(controller->target_eui_64, 0, 8);
|
||||
memset(controller->br_eui_64, 0, 8);
|
||||
memset(controller->gtkhash, 0, 32);
|
||||
|
||||
ws_pae_controller_active_nw_key_clear(&controller->nw_key[0]);
|
||||
ws_pae_controller_active_nw_key_clear(&controller->nw_key[1]);
|
||||
ws_pae_controller_active_nw_key_clear(&controller->nw_key[2]);
|
||||
ws_pae_controller_active_nw_key_clear(&controller->nw_key[3]);
|
||||
|
||||
controller->target_pan_id = 0xffff;
|
||||
controller->pae_delete = NULL;
|
||||
controller->pae_fast_timer = NULL;
|
||||
controller->pae_slow_timer = NULL;
|
||||
controller->pae_br_addr_write = NULL;
|
||||
controller->pae_br_addr_read = NULL;
|
||||
controller->pae_gtks_updated = NULL;
|
||||
controller->pae_gtk_hash_update = NULL;
|
||||
controller->pae_nw_key_index_update = NULL;
|
||||
controller->gtks_set = false;
|
||||
controller->gtkhash_set = false;
|
||||
controller->key_index_set = false;
|
||||
controller->gtk_index = -1;
|
||||
controller->network_name = NULL;
|
||||
sec_prot_keys_gtks_init(&controller->gtks);
|
||||
sec_prot_keys_gtks_init(&controller->next_gtks);
|
||||
sec_prot_certs_init(&controller->certs);
|
||||
ws_pae_timers_settings_init(&controller->timer_settings);
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_supp_init(controller->interface_ptr, &controller->certs) < 0) {
|
||||
if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->timer_settings) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
controller->pae_delete = ws_pae_supp_delete;
|
||||
controller->pae_timer = ws_pae_supp_timer;
|
||||
controller->pae_fast_timer = ws_pae_supp_fast_timer;
|
||||
controller->pae_slow_timer = ws_pae_supp_slow_timer;
|
||||
controller->pae_br_addr_write = ws_pae_supp_border_router_addr_write;
|
||||
controller->pae_br_addr_read = ws_pae_supp_border_router_addr_read;
|
||||
controller->pae_gtk_hash_update = ws_pae_supp_gtk_hash_update;
|
||||
controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update;
|
||||
|
||||
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, controller->key_insert);
|
||||
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_auth_init(controller->interface_ptr, &controller->gtks, &controller->certs) < 0) {
|
||||
if (ws_pae_auth_init(controller->interface_ptr, &controller->gtks, &controller->next_gtks, &controller->certs, &controller->timer_settings) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
controller->pae_delete = ws_pae_auth_delete;
|
||||
controller->pae_timer = ws_pae_auth_timer;
|
||||
controller->pae_fast_timer = ws_pae_auth_fast_timer;
|
||||
controller->pae_slow_timer = ws_pae_auth_slow_timer;
|
||||
controller->pae_gtks_updated = ws_pae_auth_gtks_updated;
|
||||
controller->pae_nw_key_index_update = ws_pae_auth_nw_key_index_update;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
|
@ -300,6 +571,12 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
|
|||
controller->pae_delete(interface_ptr);
|
||||
}
|
||||
|
||||
// Free data
|
||||
sec_prot_certs_delete(&controller->certs);
|
||||
|
||||
// Init controller data
|
||||
ws_pae_controller_data_init(controller);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -317,9 +594,6 @@ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr)
|
|||
}
|
||||
|
||||
ns_list_remove(&pae_controller_list, controller);
|
||||
|
||||
sec_prot_certs_delete(&controller->certs);
|
||||
|
||||
ns_dyn_mem_free(controller);
|
||||
|
||||
return 0;
|
||||
|
@ -327,29 +601,135 @@ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr)
|
|||
|
||||
int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *new_chain)
|
||||
{
|
||||
if (!new_chain) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
// Delete previous information
|
||||
sec_prot_certs_delete(&entry->certs);
|
||||
|
||||
// Adds a trusted certificate from index 0
|
||||
if (new_chain->cert_chain[0]) {
|
||||
cert_chain_entry_t *root_ca_chain = sec_prot_certs_chain_entry_create();
|
||||
sec_prot_certs_cert_set(root_ca_chain, 0, (uint8_t *) new_chain->cert_chain[0], new_chain->cert_len[0]);
|
||||
sec_prot_certs_chain_list_add(&entry->certs.trusted_cert_chain_list, root_ca_chain);
|
||||
}
|
||||
|
||||
if (new_chain->cert_chain[1] && new_chain->key_chain[1]) {
|
||||
sec_prot_certs_cert_set(&entry->certs.own_cert_chain, 0, (uint8_t *) new_chain->cert_chain[1], new_chain->cert_len[1]);
|
||||
uint8_t key_len = strlen((char *) new_chain->key_chain[1]) + 1;
|
||||
sec_prot_certs_priv_key_set(&entry->certs.own_cert_chain, (uint8_t *) new_chain->key_chain[1], key_len);
|
||||
// Adds own certificate chain from indexes 1 to 3
|
||||
for (uint8_t i = 1; i < SEC_PROT_CERT_CHAIN_DEPTH; i++) {
|
||||
if (new_chain->cert_chain[i]) {
|
||||
sec_prot_certs_cert_set(&entry->certs.own_cert_chain, i - 1, (uint8_t *) new_chain->cert_chain[i], new_chain->cert_len[i]);
|
||||
if (new_chain->key_chain[i]) {
|
||||
// Will be the key from top certificate in chain after all certificates are added
|
||||
uint8_t key_len = strlen((char *) new_chain->key_chain[i]) + 1;
|
||||
sec_prot_certs_priv_key_set(&entry->certs.own_cert_chain, (uint8_t *) new_chain->key_chain[i], key_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_trusted_certificate_add(const arm_certificate_entry_s *cert)
|
||||
{
|
||||
if (!cert) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ret = -1;
|
||||
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
cert_chain_entry_t *trusted_cert = sec_prot_certs_chain_entry_create();
|
||||
sec_prot_certs_cert_set(trusted_cert, 0, (uint8_t *) cert->cert, cert->cert_len);
|
||||
|
||||
if (sec_prot_certs_chain_list_entry_find(&entry->certs.trusted_cert_chain_list, trusted_cert)) {
|
||||
sec_prot_certs_chain_entry_delete(trusted_cert);
|
||||
continue;
|
||||
}
|
||||
sec_prot_certs_chain_list_add(&entry->certs.trusted_cert_chain_list, trusted_cert);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_trusted_certificate_remove(const arm_certificate_entry_s *cert)
|
||||
{
|
||||
if (!cert) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ret = -1;
|
||||
|
||||
cert_chain_entry_t *trusted_cert = sec_prot_certs_chain_entry_create();
|
||||
sec_prot_certs_cert_set(trusted_cert, 0, (uint8_t *) cert->cert, cert->cert_len);
|
||||
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
cert_chain_entry_t *removed_cert = sec_prot_certs_chain_list_entry_find(&entry->certs.trusted_cert_chain_list, trusted_cert);
|
||||
if (removed_cert) {
|
||||
sec_prot_certs_chain_list_entry_delete(&entry->certs.trusted_cert_chain_list, removed_cert);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sec_prot_certs_chain_entry_delete(trusted_cert);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl)
|
||||
{
|
||||
if (!crl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ret = -1;
|
||||
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
cert_revocat_list_entry_t *cert_revoc_list = sec_prot_certs_revocat_list_entry_create();
|
||||
sec_prot_certs_revocat_list_set(cert_revoc_list, crl->crl, crl->crl_len);
|
||||
|
||||
if (sec_prot_certs_revocat_lists_entry_find(&entry->certs.cert_revocat_lists, cert_revoc_list)) {
|
||||
sec_prot_certs_revocat_list_entry_delete(cert_revoc_list);
|
||||
continue;
|
||||
}
|
||||
|
||||
sec_prot_certs_revocat_lists_add(&entry->certs.cert_revocat_lists, cert_revoc_list);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl)
|
||||
{
|
||||
if (!crl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ret = -1;
|
||||
|
||||
cert_revocat_list_entry_t *cert_revoc_list = sec_prot_certs_revocat_list_entry_create();
|
||||
sec_prot_certs_revocat_list_set(cert_revoc_list, crl->crl, crl->crl_len);
|
||||
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
cert_revocat_list_entry_t *removed_cert_revoc_list = sec_prot_certs_revocat_lists_entry_find(&entry->certs.cert_revocat_lists, cert_revoc_list);
|
||||
if (removed_cert_revoc_list) {
|
||||
sec_prot_certs_revocat_lists_entry_delete(&entry->certs.cert_revocat_lists, removed_cert_revoc_list);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sec_prot_certs_revocat_list_entry_delete(cert_revoc_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
|
||||
{
|
||||
if (!interface_ptr || !eui_64) {
|
||||
if (!eui_64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -365,12 +745,11 @@ int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
|
||||
{
|
||||
if (!interface_ptr || !eui_64) {
|
||||
if (!eui_64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -388,11 +767,197 @@ int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ws_pae_controller_timer(uint16_t ticks)
|
||||
int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[4])
|
||||
{
|
||||
if (!gtk) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Removes keys set as not used
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (!gtk[i]) {
|
||||
sec_prot_keys_gtk_clear(&controller->gtks, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Inserts new keys
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (gtk[i]) {
|
||||
uint32_t lifetime = sec_prot_keys_gtk_install_order_last_lifetime_get(&controller->gtks);
|
||||
lifetime += controller->timer_settings.gtk_expire_offset;
|
||||
if (sec_prot_keys_gtk_set(&controller->gtks, i, gtk[i], lifetime) >= 0) {
|
||||
tr_info("GTK set index: %i, lifetime %"PRIu32", system time: %"PRIu32"", i, lifetime, protocol_core_monotonic_time / 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notifies PAE authenticator that GTKs have been updated */
|
||||
if (controller->pae_gtks_updated) {
|
||||
controller->pae_gtks_updated(controller->interface_ptr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_next_gtk_update(int8_t interface_id, uint8_t *gtk[4])
|
||||
{
|
||||
if (!gtk) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Inserts new keys and removed keys set as not used
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (gtk[i]) {
|
||||
sec_prot_keys_gtk_set(&controller->next_gtks, i, gtk[i], 0);
|
||||
} else {
|
||||
sec_prot_keys_gtk_clear(&controller->next_gtks, i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_active_key_update(int8_t interface_id, uint8_t index)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
controller->gtk_index = index;
|
||||
|
||||
if (controller->pae_nw_key_index_update) {
|
||||
controller->pae_nw_key_index_update(controller->interface_ptr, index);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_key_lifetime_update(int8_t interface_id, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_timers_lifetime_set(&controller->timer_settings, gtk_lifetime, pmk_lifetime, ptk_lifetime);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_gtk_time_settings_update(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_timers_gtk_time_settings_set(&controller->timer_settings, revocat_lifetime_reduct, new_activation_time, new_install_req, max_mismatch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_node_keys_remove(int8_t interface_id, uint8_t *eui_64)
|
||||
{
|
||||
#ifndef HAVE_PAE_AUTH
|
||||
(void) eui_64;
|
||||
#endif
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ws_pae_auth_node_keys_remove(controller->interface_ptr, eui_64);
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_auth_node_access_revoke_start(controller->interface_ptr);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(controller->gtkhash, gtkhash, 32);
|
||||
|
||||
tr_info("GTK hash set %s %s %s %s",
|
||||
trace_array(>khash[0], 8),
|
||||
trace_array(>khash[8], 8),
|
||||
trace_array(>khash[16], 8),
|
||||
trace_array(>khash[24], 8));
|
||||
|
||||
// Do not update PAN version for initial hash set
|
||||
if (controller->gtkhash_set) {
|
||||
if (controller->pan_ver_increment) {
|
||||
controller->pan_ver_increment(interface_ptr);
|
||||
}
|
||||
} else {
|
||||
controller->gtkhash_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *ws_pae_controller_gtk_hash_ptr_get(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return controller->gtkhash;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(controller->gtkhash, gtkhash, 32);
|
||||
|
||||
if (controller->pae_gtk_hash_update) {
|
||||
return controller->pae_gtk_hash_update(interface_ptr, gtkhash);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ws_pae_controller_fast_timer(uint16_t ticks)
|
||||
{
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
if (entry->pae_timer) {
|
||||
entry->pae_timer(ticks);
|
||||
if (entry->pae_fast_timer) {
|
||||
entry->pae_fast_timer(ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ws_pae_controller_slow_timer(uint16_t seconds)
|
||||
{
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
if (entry->pae_slow_timer) {
|
||||
entry->pae_slow_timer(seconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -408,5 +973,24 @@ static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(cur);
|
||||
|
||||
if (!controller) {
|
||||
if (ws_pae_controller_init(cur) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
controller = ws_pae_controller_get(cur);
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
||||
|
|
|
@ -124,6 +124,50 @@ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr);
|
|||
*/
|
||||
int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *chain);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_trusted_certificate_add add trusted certificate
|
||||
*
|
||||
* \param cert trusted certificate
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_trusted_certificate_add(const arm_certificate_entry_s *cert);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_trusted_certificate_remove remove trusted certificate
|
||||
*
|
||||
* \param cert trusted certificate
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_trusted_certificate_remove(const arm_certificate_entry_s *cert);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_certificate_revocation_list_add add certification revocation list
|
||||
*
|
||||
* \param crl certification revocation list
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_certificate_revocation_list_remove remove certification revocation list
|
||||
*
|
||||
* \param crl certification revocation list
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_info_set set network information
|
||||
*
|
||||
|
@ -173,14 +217,172 @@ int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_
|
|||
int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_key_insert new GTK key available callback
|
||||
* ws_pae_controller_gtk_update update GTKs (test interface)
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtk_index index of the new GTK key
|
||||
* \param gtk new GTK key
|
||||
* \param interface_id interface identifier
|
||||
* \param gtk GTK array, if GTK is not set, pointer for the index shall be NULL.
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_key_insert(protocol_interface_info_entry_t *interface_ptr, uint8_t gtk_index, uint8_t *gtk);
|
||||
int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[4]);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_next_gtk_update update next GTKs used during GTK lifecycle (test interface)
|
||||
*
|
||||
* \param interface_id interface identifier
|
||||
* \param gtk GTK array, if GTK is not set, pointer for the index shall be NULL.
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_next_gtk_update(int8_t interface_id, uint8_t *gtk[4]);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_key_lifetime_update update key lifetime
|
||||
*
|
||||
* \param interface_id interface identifier
|
||||
* \param gtk_lifetime GTK lifetime
|
||||
* \param pmk_lifetime PMK lifetime
|
||||
* \param ptk_lifetime PTK lifetime
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_key_lifetime_update(int8_t interface_id, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_gtk_time_settings_update update GTK time settings
|
||||
*
|
||||
* \param interface_id interface identifier
|
||||
* \param revocat_lifetime_reduct revocation lifetime reduction
|
||||
* \param new_activation_time new activation time
|
||||
* \param new_install_req new install required
|
||||
* \param max_mismatch max mismatch time
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_gtk_time_settings_update(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_node_keys_remove remove node's keys
|
||||
*
|
||||
* \param interface_id interface identifier
|
||||
* \param eui-64 EUI-64
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_node_keys_remove(int8_t interface_id, uint8_t *eui_64);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_node_access_revoke_start start node's access revoke
|
||||
*
|
||||
* \param interface_id interface identifier
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_active_key_update update active key (test interface)
|
||||
*
|
||||
* \param interface_id interface identifier
|
||||
* \param index GTK index
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_active_key_update(int8_t interface_id, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_gtk_hash_ptr_get get pointer to GTK hash storage
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return pointer to GTK has storage or NULL
|
||||
*
|
||||
*/
|
||||
uint8_t *ws_pae_controller_gtk_hash_ptr_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_gtk_hash_update GTK hash has been updated (on PAN configuration)
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtkhash new GTK hash
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_key_index_update key index been updated (on PAN configuration)
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param index key index
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_keys_remove remove network keys
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
*/
|
||||
void ws_pae_controller_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_key_insert network key insert callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param slot key slot (MAC key descriptor), from 0 to 4
|
||||
* \param index index of the new network key
|
||||
* \param key new key
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_nw_key_set(protocol_interface_info_entry_t *interface_ptr, uint8_t slot, uint8_t index, uint8_t *key);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_key_clear network key clear callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param slot key slot (MAC key descriptor), from 0 to 4
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_nw_key_clear(protocol_interface_info_entry_t *interface_ptr, uint8_t slot);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_send_key_index_set network send key index set callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param index index of the key to be used on sending
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_nw_send_key_index_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_frame_counter_set network frame counter set callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param counter frame counter
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_nw_frame_counter_set(protocol_interface_info_entry_t *interface_ptr, uint32_t counter);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_auth_completed authentication completed callback
|
||||
|
@ -191,26 +393,47 @@ typedef void ws_pae_controller_key_insert(protocol_interface_info_entry_t *inter
|
|||
*/
|
||||
typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *interface_ptr, bool success);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_pan_ver_increment PAN version increment callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_cb_register register PEA controller callbacks
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param completed authentication completed callback
|
||||
* \param key_insert GTK key insert callback
|
||||
* \param nw_key_set network key set callback
|
||||
* \param nw_key_clear network key clear callback
|
||||
* \param nw_send_key_index_set network send key index set callback
|
||||
* \param nw_frame_counter_set network frame counter set callback
|
||||
* \param pan_ver_increment PAN version increment callback
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_key_insert *key_insert);
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_pan_ver_increment *pan_ver_increment);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_timer PAE controller timer call
|
||||
* ws_pae_controller_fast_timer PAE controller fast timer call
|
||||
*
|
||||
* \param ticks elapsed ticks
|
||||
*
|
||||
*/
|
||||
void ws_pae_controller_timer(uint16_t ticks);
|
||||
void ws_pae_controller_fast_timer(uint16_t ticks);
|
||||
|
||||
|
||||
/**
|
||||
* ws_pae_controller_slow_timer PAE controller slow timer call
|
||||
*
|
||||
* \param seconds elapsed seconds
|
||||
*
|
||||
*/
|
||||
void ws_pae_controller_slow_timer(uint16_t seconds);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -222,14 +445,16 @@ void ws_pae_controller_timer(uint16_t ticks);
|
|||
#define ws_pae_controller_border_router_addr_write(interface_ptr, eui_64) -1
|
||||
#define ws_pae_controller_border_router_addr_read(interface_ptr, eui_64) -1
|
||||
|
||||
#define ws_pae_controller_gtk_set(interface_id, gtk) -1
|
||||
#define ws_pae_controller_next_gtks_update(interface_id, gtk) -1
|
||||
|
||||
#define ws_pae_controller_init(interface_ptr) 1
|
||||
#define ws_pae_controller_supp_init(interface_ptr) 1
|
||||
#define ws_pae_controller_auth_init(interface_ptr) 1
|
||||
|
||||
#define ws_pae_controller_stop(interface_ptr)
|
||||
#define ws_pae_controller_delete(interface_ptr)
|
||||
#define ws_pae_controller_cb_register(interface_ptr, completed, key_insert) 1
|
||||
#define ws_pae_controller_timer(ticks)
|
||||
#define ws_pae_controller_cb_register(interface_ptr, completed, nw_key_set, nw_key_clear, nw_send_key_index_set, pan_ver_increment) 1
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "Security/kmp/kmp_api.h"
|
||||
#include "Security/protocols/sec_prot_certs.h"
|
||||
#include "Security/protocols/sec_prot_keys.h"
|
||||
#include "6LoWPAN/ws/ws_pae_timers.h"
|
||||
#include "6LoWPAN/ws/ws_pae_lib.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
@ -208,13 +209,28 @@ bool ws_pae_lib_supp_list_timer_update(supp_list_t *active_supp_list, supp_list_
|
|||
return timer_running;
|
||||
}
|
||||
|
||||
void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, timer_settings_t *timer_settings, uint16_t seconds)
|
||||
{
|
||||
ns_list_foreach(supp_entry_t, entry, supp_list) {
|
||||
if (sec_prot_keys_pmk_lifetime_decrement(&entry->sec_keys, timer_settings->pmk_lifetime, seconds)) {
|
||||
tr_info("PMK and PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(kmp_address_eui_64_get(entry->addr), 8), protocol_core_monotonic_time / 10);
|
||||
}
|
||||
if (sec_prot_keys_ptk_lifetime_decrement(&entry->sec_keys, timer_settings->ptk_lifetime, seconds)) {
|
||||
tr_info("PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(kmp_address_eui_64_get(entry->addr), 8), protocol_core_monotonic_time / 10);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ws_pae_lib_supp_init(supp_entry_t *entry)
|
||||
{
|
||||
ws_pae_lib_kmp_list_init(&entry->kmp_list);
|
||||
entry->addr = 0;
|
||||
memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t));
|
||||
entry->ticks = 0;
|
||||
entry->retry_ticks = 0;
|
||||
entry->active = true;
|
||||
entry->access_revoked = false;
|
||||
}
|
||||
|
||||
void ws_pae_lib_supp_delete(supp_entry_t *entry)
|
||||
|
@ -235,9 +251,20 @@ bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_li
|
|||
entry->ticks -= ticks;
|
||||
} else {
|
||||
entry->ticks = 0;
|
||||
entry->retry_ticks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates retry timer
|
||||
if (entry->retry_ticks > ticks) {
|
||||
entry->retry_ticks -= ticks;
|
||||
} else {
|
||||
if (entry->retry_ticks > 0) {
|
||||
tr_info("EAP-TLS max ongoing delay timeout eui-64: %s", trace_array(kmp_address_eui_64_get(entry->addr), 8));
|
||||
}
|
||||
entry->retry_ticks = 0;
|
||||
}
|
||||
|
||||
return keep_timer_running;
|
||||
}
|
||||
|
||||
|
@ -274,6 +301,12 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t
|
|||
|
||||
tr_debug("PAE: to inactive, eui-64: %s", trace_array(kmp_address_eui_64_get(entry->addr), 8));
|
||||
|
||||
if (entry->access_revoked) {
|
||||
tr_info("Access revoked; deleted, eui-64: %s", trace_array(kmp_address_eui_64_get(entry->addr), 8));
|
||||
ws_pae_lib_supp_list_remove(active_supp_list, entry);
|
||||
return;
|
||||
}
|
||||
|
||||
ns_list_remove(active_supp_list, entry);
|
||||
ns_list_add_to_start(inactive_supp_list, entry);
|
||||
|
||||
|
@ -286,4 +319,35 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t
|
|||
entry->addr = addr;
|
||||
}
|
||||
|
||||
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
|
||||
{
|
||||
uint16_t kmp_count = 0;
|
||||
|
||||
ns_list_foreach(supp_entry_t, entry, supp_list) {
|
||||
ns_list_foreach(kmp_entry_t, kmp_entry, &entry->kmp_list) {
|
||||
if (kmp_api_type_get(kmp_entry->kmp) == type) {
|
||||
kmp_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return kmp_count;
|
||||
}
|
||||
|
||||
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
|
||||
{
|
||||
supp_entry_t *retry_supp = NULL;
|
||||
|
||||
ns_list_foreach(supp_entry_t, entry, supp_list) {
|
||||
// Finds entry with shortest timeout i.e. oldest one
|
||||
if (entry->retry_ticks > 0) {
|
||||
if (!retry_supp || retry_supp->retry_ticks > entry->retry_ticks) {
|
||||
retry_supp = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retry_supp;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
#ifndef WS_PAE_LIB_H_
|
||||
#define WS_PAE_LIB_H_
|
||||
|
||||
/*
|
||||
* Port access entity library functions.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
kmp_api_t *kmp; /**< KMP API */
|
||||
bool timer_running; /**< Timer running inside KMP */
|
||||
|
@ -31,7 +36,9 @@ typedef struct {
|
|||
kmp_addr_t *addr; /**< EUI-64 (Relay IP address, Relay port) */
|
||||
sec_prot_keys_t sec_keys; /**< Security keys */
|
||||
uint32_t ticks; /**< Ticks */
|
||||
bool active; /**< Is active */
|
||||
uint16_t retry_ticks; /**< Retry ticks */
|
||||
bool active : 1; /**< Is active */
|
||||
bool access_revoked : 1; /**< Nodes access is revoked */
|
||||
ns_list_link_t link; /**< Link */
|
||||
} supp_entry_t;
|
||||
|
||||
|
@ -144,11 +151,6 @@ typedef void ws_pae_lib_kmp_timer_timeout(kmp_api_t *kmp, uint16_t ticks);
|
|||
*/
|
||||
bool ws_pae_lib_kmp_timer_update(kmp_list_t *kmp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_init initiates supplicant list
|
||||
*
|
||||
|
@ -211,6 +213,16 @@ void ws_pae_lib_supp_list_delete(supp_list_t *supp_list);
|
|||
*/
|
||||
bool ws_pae_lib_supp_list_timer_update(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_slow_timer_update updates slow timer on supplicant list
|
||||
*
|
||||
* \param supp_list list of supplicants
|
||||
* \param timer_settings timer settings
|
||||
* \param seconds seconds
|
||||
*
|
||||
*/
|
||||
void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, timer_settings_t *timer_settings, uint16_t seconds);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_timer_update updates supplicant timers
|
||||
*
|
||||
|
@ -268,4 +280,25 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
|
|||
*/
|
||||
void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants
|
||||
*
|
||||
* \param supp_list list of supplicants
|
||||
* \param type KMP type
|
||||
*
|
||||
* \return number of KMPs in the supplicant list
|
||||
*
|
||||
*/
|
||||
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_entry_retry_timer_get checks if some supplicant has retry timer running
|
||||
*
|
||||
* \param supp_list list of supplicants
|
||||
*
|
||||
* \return supplicant with retry timer running or NULL if no supplicants with timer running
|
||||
*
|
||||
*/
|
||||
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list);
|
||||
|
||||
#endif /* WS_PAE_AUTH_H_ */
|
||||
|
|
|
@ -104,8 +104,7 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *p
|
|||
if (*tlv++ == 1) { /* GTK is set */
|
||||
uint32_t lifetime = common_read_32_bit(tlv);
|
||||
tlv += 4;
|
||||
sec_prot_keys_gtk_set(gtks, i, tlv);
|
||||
sec_prot_keys_gtk_lifetime_set(gtks, i, lifetime);
|
||||
sec_prot_keys_gtk_set(gtks, i, tlv, lifetime);
|
||||
tlv += GTK_LEN;
|
||||
} else {
|
||||
tlv += 4 + GTK_LEN;
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
#ifndef WS_PAE_NVM_DATA_H_
|
||||
#define WS_PAE_NVM_DATA_H_
|
||||
|
||||
/*
|
||||
* Port access entity non-volatile memory (NVM) data module. Module is used
|
||||
* to create and parse PAE NVM data TLVs.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* ws_pae_nvm_store_nw_info_tlv_create create NVM network info TLV
|
||||
*
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
#ifndef WS_PAE_NVM_STORE_H_
|
||||
#define WS_PAE_NVM_STORE_H_
|
||||
|
||||
/*
|
||||
* Port access entity non-volatile memory (NVM) storage module. Module is used
|
||||
* to write and read PAE NVM data TLVs to/from filesystem.
|
||||
*
|
||||
*/
|
||||
|
||||
// tag + length
|
||||
#define NVM_TLV_FIXED_LEN 4
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include <randLIB.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
|
@ -41,6 +42,7 @@
|
|||
#include "Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h"
|
||||
#include "Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "6LoWPAN/ws/ws_pae_timers.h"
|
||||
#include "6LoWPAN/ws/ws_pae_supp.h"
|
||||
#include "6LoWPAN/ws/ws_pae_lib.h"
|
||||
#include "6LoWPAN/ws/ws_pae_nvm_store.h"
|
||||
|
@ -61,16 +63,24 @@
|
|||
// Wait for for authenticator to continue with authentication (e.g. after EAP-TLS to initiate 4WH)
|
||||
#define WAIT_FOR_AUTHENTICATION_TICKS 30 * 10 // 30 seconds
|
||||
|
||||
// Wait for re-authentication after GTK update
|
||||
#define WAIT_FOR_REAUTHENTICATION_TICKS 120 * 10 // 120 seconds
|
||||
|
||||
// How many times in maximum stored keys are used for authentication
|
||||
#define STORED_KEYS_MAXIMUM_USE_COUNT 2
|
||||
|
||||
// Delay for sending the initial EAPOL-Key
|
||||
#define INITIAL_KEY_TIMER_MIN 3
|
||||
#define INITIAL_KEY_TIMER_MAX 30
|
||||
|
||||
const char *NW_INFO_FILE = "pae_nw_info";
|
||||
const char *KEYS_FILE = "pae_keys";
|
||||
|
||||
typedef struct {
|
||||
char network_name[33]; /**< Network name for keys */
|
||||
sec_prot_gtk_keys_t *gtks; /**< Link to GTKs */
|
||||
uint16_t pan_id; /**< PAN ID for keys */
|
||||
uint16_t new_pan_id; /**< new PAN ID indicated by bootstrap */
|
||||
uint16_t key_pan_id; /**< PAN ID for keys */
|
||||
bool updated : 1; /**< Network info has been updated */
|
||||
} sec_prot_keys_nw_info_t;
|
||||
|
||||
|
@ -79,25 +89,31 @@ typedef struct {
|
|||
kmp_service_t *kmp_service; /**< KMP service */
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< Interface */
|
||||
ws_pae_supp_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
|
||||
ws_pae_supp_key_insert *key_insert; /**< Key insert callback */
|
||||
ws_pae_supp_nw_key_insert *nw_key_insert; /**< Key insert callback */
|
||||
ws_pae_supp_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
|
||||
supp_entry_t entry; /**< Supplicant data */
|
||||
kmp_addr_t target_addr; /**< EAPOL target (parent) address */
|
||||
trickle_t auth_trickle_timer; /**< Trickle timer for re-sending initial EAPOL-key */
|
||||
uint16_t initial_key_timer; /**< Timer to trigger initial EAPOL-Key */
|
||||
trickle_t auth_trickle_timer; /**< Trickle timer for re-sending initial EAPOL-key or for GTK mismatch */
|
||||
trickle_params_t auth_trickle_params; /**< Trickle parameters for initial EAPOL-key or for GTK mismatch */
|
||||
sec_prot_gtk_keys_t gtks; /**< GTKs */
|
||||
uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap */
|
||||
uint8_t ptk_eui_64[8]; /**< Border router EUI-64 used on PTK generation */
|
||||
sec_prot_keys_nw_info_t sec_keys_nw_info; /**< Security keys network information */
|
||||
timer_settings_t *timer_settings; /**< Timer settings */
|
||||
uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */
|
||||
bool auth_trickle_running : 1; /**< Trickle timer running */
|
||||
bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */
|
||||
bool auth_requested : 1; /**< Authentication has been requested */
|
||||
bool timer_running : 1; /**< Timer is running */
|
||||
bool new_br_eui_64_set : 1; /**< Border router address has been set */
|
||||
bool new_br_eui_64_fresh : 1; /**< Border router address is fresh (set during this authentication attempt) */
|
||||
} pae_supp_t;
|
||||
|
||||
// Wi-SUN specification states initial retransmission to be around 5 minutes and maximum 60 minutes
|
||||
static const trickle_params_t auth_trickle_params = {
|
||||
.Imin = 30 * 10, /* 30s; ticks are 100ms */
|
||||
.Imax = 60 * 10, /* 60s */
|
||||
|
||||
#define TRICKLE_IMIN_180_SECS 180
|
||||
|
||||
static trickle_params_t initial_eapol_key_trickle_params = {
|
||||
.Imin = TRICKLE_IMIN_180_SECS, /* 180 second; ticks are 1 second */
|
||||
.Imax = TRICKLE_IMIN_180_SECS << 1, /* 360 second */
|
||||
.k = 0, /* infinity - no consistency checking */
|
||||
.TimerExpirations = 3
|
||||
};
|
||||
|
@ -122,6 +138,7 @@ static kmp_api_t *ws_pae_supp_kmp_service_api_get(kmp_service_t *service, kmp_ap
|
|||
static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr);
|
||||
static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp);
|
||||
static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
|
||||
|
||||
static void ws_pae_supp_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result);
|
||||
static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr);
|
||||
|
@ -152,29 +169,33 @@ int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr,
|
|||
// Delete GTKs
|
||||
sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info.gtks);
|
||||
|
||||
/* PAN ID has changed, delete key data associated with border router
|
||||
i.e PMK, PTK, EA-IE data (border router EUI-64) */
|
||||
if (pae_supp->sec_keys_nw_info.key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info.key_pan_id != dest_pan_id) {
|
||||
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
|
||||
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
|
||||
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
|
||||
}
|
||||
|
||||
pae_supp->sec_keys_nw_info.key_pan_id = dest_pan_id;
|
||||
|
||||
// Prepare to receive new border router address
|
||||
pae_supp->new_br_eui_64_set = false;
|
||||
pae_supp->new_br_eui_64_fresh = false;
|
||||
|
||||
// Stores target/parent address
|
||||
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, dest_eui_64);
|
||||
// Sets target address in use
|
||||
pae_supp->entry.addr = (kmp_addr_t *) &pae_supp->target_addr;
|
||||
|
||||
// Sends initial EAPOL-Key message
|
||||
if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
|
||||
pae_supp->auth_completed(interface_ptr, false);
|
||||
}
|
||||
pae_supp->auth_requested = true;
|
||||
|
||||
// Starts trickle
|
||||
trickle_start(&pae_supp->auth_trickle_timer, &auth_trickle_params);
|
||||
pae_supp->auth_trickle_running = true;
|
||||
// Randomizes the sending of initial EAPOL-Key messsage
|
||||
pae_supp->initial_key_timer = randLIB_get_random_in_range(INITIAL_KEY_TIMER_MIN, INITIAL_KEY_TIMER_MAX);
|
||||
|
||||
// Starts supplicant timer
|
||||
ws_pae_supp_timer_start(pae_supp);
|
||||
|
||||
pae_supp->auth_requested = true;
|
||||
|
||||
tr_debug("PAE active");
|
||||
tr_debug("PAE active, timer %i", pae_supp->initial_key_timer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -187,8 +208,8 @@ int8_t ws_pae_supp_nw_info_set(protocol_interface_info_entry_t *interface_ptr, u
|
|||
}
|
||||
|
||||
// PAN ID has been modified
|
||||
if (pan_id != 0xffff && pan_id != pae_supp->sec_keys_nw_info.pan_id) {
|
||||
pae_supp->sec_keys_nw_info.pan_id = pan_id;
|
||||
if (pan_id != 0xffff && pan_id != pae_supp->sec_keys_nw_info.new_pan_id) {
|
||||
pae_supp->sec_keys_nw_info.new_pan_id = pan_id;
|
||||
pae_supp->sec_keys_nw_info.updated = true;
|
||||
}
|
||||
|
||||
|
@ -211,6 +232,7 @@ int8_t ws_pae_supp_border_router_addr_write(protocol_interface_info_entry_t *int
|
|||
|
||||
memcpy(pae_supp->new_br_eui_64, eui_64, 8);
|
||||
pae_supp->new_br_eui_64_set = true;
|
||||
pae_supp->new_br_eui_64_fresh = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -222,11 +244,12 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!pae_supp->entry.sec_keys.ptk_eui_64 || !pae_supp->entry.sec_keys.ptk_eui_64_set) {
|
||||
uint8_t *br_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
|
||||
if (!br_eui_64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(eui_64, pae_supp->entry.sec_keys.ptk_eui_64, 8);
|
||||
memcpy(eui_64, br_eui_64, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -238,6 +261,8 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("NW key valid");
|
||||
|
||||
// Stored keys are valid
|
||||
pae_supp->nw_keys_used_cnt = 0;
|
||||
|
||||
|
@ -247,6 +272,69 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||
if (!pae_supp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check GTK hashes and initiate EAPOL procedure if mismatch is detected */
|
||||
gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(&pae_supp->gtks, gtkhash);
|
||||
if (mismatch > GTK_NO_MISMATCH) {
|
||||
tr_info("GTK hash update %s %s %s %s",
|
||||
trace_array(>khash[0], 8),
|
||||
trace_array(>khash[8], 8),
|
||||
trace_array(>khash[16], 8),
|
||||
trace_array(>khash[24], 8));
|
||||
|
||||
// Mismatch, initiate EAPOL
|
||||
if (!pae_supp->auth_trickle_running) {
|
||||
uint8_t timer_expirations = 3;
|
||||
// For GTK lifetime mismatch send only once
|
||||
if (mismatch == GTK_LIFETIME_MISMATCH) {
|
||||
timer_expirations = 1;
|
||||
}
|
||||
|
||||
pae_supp->auth_trickle_params.Imin = pae_supp->timer_settings->gtk_request_imin;
|
||||
pae_supp->auth_trickle_params.Imax = pae_supp->timer_settings->gtk_request_imax;
|
||||
pae_supp->auth_trickle_params.k = 0;
|
||||
pae_supp->auth_trickle_params.TimerExpirations = timer_expirations;
|
||||
|
||||
// Starts trickle
|
||||
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
|
||||
pae_supp->auth_trickle_running = true;
|
||||
|
||||
// Starts supplicant timer
|
||||
ws_pae_supp_timer_start(pae_supp);
|
||||
|
||||
tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->timer_settings->gtk_request_imin, pae_supp->timer_settings->gtk_request_imax, pae_supp->timer_settings->gtk_max_mismatch, pae_supp->auth_trickle_timer.t);
|
||||
}
|
||||
}
|
||||
|
||||
// Modify keys
|
||||
pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info.gtks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||
if (!pae_supp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sec_prot_keys_gtk_status_active_set(&pae_supp->gtks, index) >= 0) {
|
||||
tr_info("NW send key index set: %i", index + 1);
|
||||
pae_supp->nw_key_index_set(interface_ptr, index);
|
||||
} else {
|
||||
tr_info("NW send key index: %i, no changes", index + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp)
|
||||
{
|
||||
// Check if NW info or GTKs have been changed
|
||||
|
@ -268,7 +356,7 @@ static int8_t ws_pae_supp_nvm_nw_info_write(pae_supp_t *pae_supp)
|
|||
nvm_tlv_list_t tlv_list;
|
||||
ns_list_init(&tlv_list);
|
||||
|
||||
nvm_tlv_entry_t *tlv_entry = ws_pae_nvm_store_nw_info_tlv_create(pae_supp->sec_keys_nw_info.pan_id,
|
||||
nvm_tlv_entry_t *tlv_entry = ws_pae_nvm_store_nw_info_tlv_create(pae_supp->sec_keys_nw_info.key_pan_id,
|
||||
pae_supp->sec_keys_nw_info.network_name,
|
||||
&pae_supp->gtks);
|
||||
ns_list_add_to_end(&tlv_list, tlv_entry);
|
||||
|
@ -288,7 +376,7 @@ static int8_t ws_pae_supp_nvm_nw_info_read(pae_supp_t *pae_supp)
|
|||
ws_pae_nvm_store_tlv_file_read(NW_INFO_FILE, &tlv_list);
|
||||
|
||||
ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
|
||||
ws_pae_nvm_store_nw_info_tlv_read(entry, &pae_supp->sec_keys_nw_info.pan_id,
|
||||
ws_pae_nvm_store_nw_info_tlv_read(entry, &pae_supp->sec_keys_nw_info.key_pan_id,
|
||||
pae_supp->sec_keys_nw_info.network_name,
|
||||
&pae_supp->gtks);
|
||||
ns_list_remove(&tlv_list, entry);
|
||||
|
@ -340,11 +428,29 @@ static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, bool success
|
|||
|
||||
static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp)
|
||||
{
|
||||
if (!pae_supp->auth_requested) {
|
||||
// If not making initial authentication updates target (RPL parent) for each EAPOL-key message
|
||||
uint8_t parent_eui_64[8];
|
||||
if (ws_pae_supp_parent_eui_64_get(pae_supp->interface_ptr, parent_eui_64) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Stores target/parent address
|
||||
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, parent_eui_64);
|
||||
// Sets parent address in use
|
||||
pae_supp->entry.addr = (kmp_addr_t *) &pae_supp->target_addr;
|
||||
|
||||
ws_pae_lib_supp_timer_ticks_set(&pae_supp->entry, WAIT_FOR_REAUTHENTICATION_TICKS);
|
||||
tr_info("PAE wait for auth seconds: %i", WAIT_FOR_REAUTHENTICATION_TICKS / 10);
|
||||
}
|
||||
|
||||
kmp_api_t *kmp = ws_pae_supp_kmp_create_and_start(pae_supp->kmp_service, IEEE_802_1X_MKA_KEY, pae_supp);
|
||||
if (!kmp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_info("EAPOL target: %s", trace_array(kmp_address_eui_64_get(pae_supp->entry.addr), 8));
|
||||
|
||||
kmp_api_create_request(kmp, IEEE_802_1X_MKA_KEY, pae_supp->entry.addr, &pae_supp->entry.sec_keys);
|
||||
|
||||
return 0;
|
||||
|
@ -365,34 +471,21 @@ static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan
|
|||
return -1;
|
||||
}
|
||||
|
||||
// First attempt to authenticate, checks if keys exists
|
||||
if (pae_supp->nw_keys_used_cnt == 0 && pan_id == pae_supp->sec_keys_nw_info.pan_id) {
|
||||
sec_prot_gtk_keys_t *gtks = pae_supp->sec_keys_nw_info.gtks;
|
||||
|
||||
bool key_inserted = false;
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
|
||||
if (gtk) {
|
||||
// Insert also non-live keys since GTK hash information not yet received
|
||||
pae_supp->key_insert(pae_supp->interface_ptr, i, gtk);
|
||||
key_inserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (key_inserted) {
|
||||
tr_debug("Keys inserted");
|
||||
pae_supp->nw_keys_used_cnt++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pae_supp->nw_keys_used_cnt == 0) {
|
||||
return -1;
|
||||
} else {
|
||||
/* Checks if keys match to PAN ID and that needed keys exists (PMK, PTK and a GTK),
|
||||
and calls inserts function that will update the network keys as needed */
|
||||
if ((pan_id == pae_supp->sec_keys_nw_info.key_pan_id) &&
|
||||
(sec_prot_keys_gtk_count(pae_supp->sec_keys_nw_info.gtks) > 0) &&
|
||||
(sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) &&
|
||||
(sec_prot_keys_ptk_get(&pae_supp->entry.sec_keys) != NULL)) {
|
||||
tr_debug("Existing keys used, counter %i", pae_supp->nw_keys_used_cnt);
|
||||
if (pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info.gtks) >= 0) {
|
||||
tr_debug("Keys inserted");
|
||||
}
|
||||
pae_supp->nw_keys_used_cnt++;
|
||||
return 0;
|
||||
} else {
|
||||
pae_supp->nw_keys_used_cnt = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,10 +498,12 @@ static void ws_pae_supp_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_i
|
|||
memset(sec_keys_nw_info, 0, sizeof(sec_prot_keys_nw_info_t));
|
||||
|
||||
sec_keys_nw_info->gtks = gtks;
|
||||
sec_keys_nw_info->new_pan_id = 0xFFFF;
|
||||
sec_keys_nw_info->key_pan_id = 0xFFFF;
|
||||
sec_keys_nw_info->updated = false;
|
||||
}
|
||||
|
||||
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_key_insert *key_insert)
|
||||
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||
if (!pae_supp) {
|
||||
|
@ -416,10 +511,11 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
|
|||
}
|
||||
|
||||
pae_supp->auth_completed = completed;
|
||||
pae_supp->key_insert = key_insert;
|
||||
pae_supp->nw_key_insert = nw_key_insert;
|
||||
pae_supp->nw_key_index_set = nw_key_index_set;
|
||||
}
|
||||
|
||||
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs)
|
||||
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, timer_settings_t *timer_settings)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
|
@ -435,10 +531,17 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
|
|||
}
|
||||
|
||||
pae_supp->interface_ptr = interface_ptr;
|
||||
pae_supp->auth_completed = 0;
|
||||
pae_supp->key_insert = 0;
|
||||
pae_supp->auth_trickle_running = false;
|
||||
pae_supp->auth_completed = NULL;
|
||||
pae_supp->nw_key_insert = NULL;
|
||||
pae_supp->nw_key_index_set = NULL;
|
||||
pae_supp->initial_key_timer = 0;
|
||||
pae_supp->nw_keys_used_cnt = 0;
|
||||
pae_supp->timer_settings = timer_settings;
|
||||
pae_supp->auth_trickle_running = false;
|
||||
pae_supp->auth_requested = false;
|
||||
pae_supp->timer_running = false;
|
||||
pae_supp->new_br_eui_64_set = false;
|
||||
pae_supp->new_br_eui_64_fresh = false;
|
||||
|
||||
ws_pae_lib_supp_init(&pae_supp->entry);
|
||||
|
||||
|
@ -449,8 +552,6 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
|
|||
sec_prot_keys_gtks_init(&pae_supp->gtks);
|
||||
sec_prot_keys_init(&pae_supp->entry.sec_keys, &pae_supp->gtks, certs);
|
||||
memset(pae_supp->new_br_eui_64, 0, 8);
|
||||
memset(pae_supp->ptk_eui_64, 0, 8);
|
||||
sec_prot_keys_ptk_eui_64_set(&pae_supp->entry.sec_keys, pae_supp->ptk_eui_64);
|
||||
|
||||
pae_supp->kmp_service = kmp_service_create();
|
||||
if (!pae_supp->kmp_service) {
|
||||
|
@ -619,29 +720,18 @@ static void ws_pae_supp_tasklet_handler(arm_event_s *event)
|
|||
}
|
||||
}
|
||||
|
||||
void ws_pae_supp_timer(uint16_t ticks)
|
||||
void ws_pae_supp_fast_timer(uint16_t ticks)
|
||||
{
|
||||
ns_list_foreach(pae_supp_t, pae_supp, &pae_supp_list) {
|
||||
if (!ws_pae_supp_timer_running(pae_supp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Checks whether initial EAPOL-Key message needs to be re-send
|
||||
if (pae_supp->auth_trickle_running) {
|
||||
if (trickle_timer(&pae_supp->auth_trickle_timer, &auth_trickle_params, ticks)) {
|
||||
ws_pae_supp_initial_key_send(pae_supp);
|
||||
}
|
||||
// Maximum number of trickle expires, authentication fails
|
||||
if (!trickle_running(&pae_supp->auth_trickle_timer, &auth_trickle_params)) {
|
||||
ws_pae_supp_authenticate_response(pae_supp, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Updates KMP timers and supplicant authentication ongoing timer
|
||||
bool running = ws_pae_lib_supp_timer_update(&pae_supp->entry, ticks, kmp_service_timer_if_timeout);
|
||||
|
||||
// Checks whether timer needs to be active
|
||||
if (!pae_supp->auth_trickle_running && !running) {
|
||||
if (!pae_supp->initial_key_timer && !pae_supp->auth_trickle_running && !running) {
|
||||
|
||||
tr_debug("PAE idle");
|
||||
// Sets target/parent address to null
|
||||
|
@ -655,6 +745,48 @@ void ws_pae_supp_timer(uint16_t ticks)
|
|||
}
|
||||
}
|
||||
|
||||
void ws_pae_supp_slow_timer(uint16_t seconds)
|
||||
{
|
||||
ns_list_foreach(pae_supp_t, pae_supp, &pae_supp_list) {
|
||||
|
||||
// Checks whether initial EAPOL-Key message needs to be re-send or new GTK request to be sent
|
||||
if (pae_supp->auth_trickle_running) {
|
||||
if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) {
|
||||
ws_pae_supp_initial_key_send(pae_supp);
|
||||
}
|
||||
// Maximum number of trickle expires, authentication fails
|
||||
if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) {
|
||||
ws_pae_supp_authenticate_response(pae_supp, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Decrements GTK lifetimes
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (!sec_prot_keys_gtk_is_set(&pae_supp->gtks, i)) {
|
||||
continue;
|
||||
}
|
||||
sec_prot_keys_gtk_lifetime_decrement(&pae_supp->gtks, i, seconds);
|
||||
}
|
||||
|
||||
if (pae_supp->initial_key_timer > 0) {
|
||||
if (pae_supp->initial_key_timer > seconds) {
|
||||
pae_supp->initial_key_timer -= seconds;
|
||||
} else {
|
||||
pae_supp->initial_key_timer = 0;
|
||||
|
||||
// Sends initial EAPOL-Key message
|
||||
ws_pae_supp_initial_key_send(pae_supp);
|
||||
|
||||
// Starts trickle
|
||||
pae_supp->auth_trickle_params = initial_eapol_key_trickle_params;
|
||||
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
|
||||
pae_supp->auth_trickle_running = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
|
||||
|
@ -720,21 +852,38 @@ static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_
|
|||
}
|
||||
}
|
||||
|
||||
rpl_dodag_info_t dodag_info;
|
||||
struct rpl_instance *instance = rpl_control_enumerate_instances(interface_ptr->rpl_domain, NULL);
|
||||
if (instance && rpl_control_read_dodag_info(instance, &dodag_info)) {
|
||||
// Get parent
|
||||
const uint8_t *parent_ll_addr = rpl_control_preferred_parent_addr(instance, false);
|
||||
uint8_t parent_eui_64[8];
|
||||
if (ws_pae_supp_parent_eui_64_get(interface_ptr, parent_eui_64) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Message from RPL parent, route to self
|
||||
if (parent_ll_addr && memcmp(&parent_ll_addr[8], eui_64, 8) == 0) {
|
||||
if (memcmp(parent_eui_64, eui_64, 8) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
|
||||
{
|
||||
rpl_dodag_info_t dodag_info;
|
||||
if (!interface_ptr->rpl_domain) {
|
||||
return -1;
|
||||
}
|
||||
struct rpl_instance *instance = rpl_control_enumerate_instances(interface_ptr->rpl_domain, NULL);
|
||||
if (instance && rpl_control_read_dodag_info(instance, &dodag_info)) {
|
||||
// Get parent
|
||||
const uint8_t *parent_ll_addr = rpl_control_preferred_parent_addr(instance, false);
|
||||
if (parent_ll_addr) {
|
||||
memcpy(eui_64, &parent_ll_addr[8], 8);
|
||||
eui_64[0] |= 0x02;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ws_pae_supp_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr)
|
||||
|
@ -752,14 +901,24 @@ static void ws_pae_supp_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *
|
|||
kmp_address_eui_64_set(local_addr, mac_params.mac_long);
|
||||
}
|
||||
|
||||
if (pae_supp->new_br_eui_64_set) {
|
||||
// BR address has been received during authentication attempt
|
||||
if (pae_supp->new_br_eui_64_fresh) {
|
||||
kmp_address_eui_64_set(remote_addr, pae_supp->new_br_eui_64);
|
||||
} else if (pae_supp->entry.sec_keys.ptk_eui_64_set) {
|
||||
kmp_address_eui_64_set(remote_addr, pae_supp->entry.sec_keys.ptk_eui_64);
|
||||
} else {
|
||||
memset(remote_addr, 0, 8);
|
||||
uint8_t *eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
|
||||
// BR address is set on security keys (confirmed using 4WH)
|
||||
if (eui_64) {
|
||||
kmp_address_eui_64_set(remote_addr, eui_64);
|
||||
} else {
|
||||
// For initial EAPOL key, if BR address has been received during previous attempt, generate PMKID using it
|
||||
if (pae_supp->new_br_eui_64_set && kmp_api_type_get(kmp) >= IEEE_802_1X_INITIAL_KEY) {
|
||||
kmp_address_eui_64_set(remote_addr, pae_supp->new_br_eui_64);
|
||||
} else {
|
||||
memset(remote_addr, 0, sizeof(kmp_addr_t));
|
||||
tr_error("No border router EUI-64");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static kmp_api_t *ws_pae_supp_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type)
|
||||
|
@ -897,18 +1056,12 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
|
|||
ws_pae_lib_supp_timer_ticks_set(&pae_supp->entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||
}
|
||||
|
||||
if ((type == IEEE_802_11_4WH || type == IEEE_802_11_GKH) && result == KMP_RESULT_OK) {
|
||||
if (sec_keys) {
|
||||
sec_prot_keys_t *keys = sec_keys;
|
||||
// Key is to be inserted
|
||||
if (keys) {
|
||||
uint8_t gtk_index;
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(keys->gtks, >k_index);
|
||||
if (gtk) {
|
||||
pae_supp->key_insert(pae_supp->interface_ptr, gtk_index, gtk);
|
||||
sec_prot_keys_gtk_insert_index_clear(keys->gtks);
|
||||
}
|
||||
pae_supp->nw_key_insert(pae_supp->interface_ptr, keys->gtks);
|
||||
}
|
||||
|
||||
if ((type == IEEE_802_11_4WH || type == IEEE_802_11_GKH) && result == KMP_RESULT_OK) {
|
||||
ws_pae_supp_authenticate_response(pae_supp, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,12 +38,13 @@
|
|||
*
|
||||
* \param interface_ptr interface
|
||||
* \param cert_chain certificate chain
|
||||
* \param timer_settings timer settings
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs);
|
||||
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, timer_settings_t *timer_settings);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_delete deletes PAE supplicant
|
||||
|
@ -57,12 +58,20 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
|
|||
int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_timer PAE supplicant timer call
|
||||
* ws_pae_supp_fast_timer PAE supplicant fast timer call
|
||||
*
|
||||
* \param ticks elapsed ticks
|
||||
*
|
||||
*/
|
||||
void ws_pae_supp_timer(uint16_t ticks);
|
||||
void ws_pae_supp_fast_timer(uint16_t ticks);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_slow_timer PAE supplicant slow timer call
|
||||
*
|
||||
* \param ticks elapsed seconds
|
||||
*
|
||||
*/
|
||||
void ws_pae_supp_slow_timer(uint16_t seconds);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_authenticate start EAPOL authentication
|
||||
|
@ -126,6 +135,39 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte
|
|||
*/
|
||||
int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_gtk_hash_update GTK hash has been updated (on PAN configuration)
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtkhash GTK hash, 32 bytes
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_nw_key_index_update key index been updated (on PAN configuration)
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param index key index
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_nw_key_index_set network send key index set callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param index network send key index
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_supp_nw_key_index_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_auth_completed authentication completed callback
|
||||
*
|
||||
|
@ -136,36 +178,42 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr);
|
|||
typedef void ws_pae_supp_auth_completed(protocol_interface_info_entry_t *interface_ptr, bool success);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_key_insert new GTK key available
|
||||
* ws_pae_supp_nw_key_insert network key insert callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtk_index index of the new GTK key
|
||||
* \param gtk new GTK key
|
||||
* \param gtks group keys
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_supp_key_insert(protocol_interface_info_entry_t *interface_ptr, uint8_t gtk_index, uint8_t *gtk);
|
||||
typedef int8_t ws_pae_supp_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_cb_register register PEA supplicant callbacks
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param completed authentication completed callback
|
||||
* \param key_insert GTK key insert callback
|
||||
* \param nw_key_insert network key index callback
|
||||
* \param nw_key_index_set network send key index callback
|
||||
*
|
||||
*/
|
||||
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_key_insert *key_insert);
|
||||
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_pae_supp_init(interface_ptr, certs) 1
|
||||
#define ws_pae_supp_init(interface_ptr, certs, timer_settings) 1
|
||||
#define ws_pae_supp_delete NULL
|
||||
#define ws_pae_supp_cb_register(interface_ptr, completed, key_insert)
|
||||
#define ws_pae_supp_cb_register(interface_ptr, completed, nw_key_insert, nw_key_index_set)
|
||||
#define ws_pae_supp_nw_info_set(interface_ptr, pan_id, network_name) -1
|
||||
#define ws_pae_supp_nw_key_valid(interface_ptr) -1
|
||||
#define ws_pae_supp_timer NULL
|
||||
#define ws_pae_supp_fast_timer NULL
|
||||
#define ws_pae_supp_slow_timer NULL
|
||||
#define ws_pae_supp_authenticate(interface_ptr, dest_pan_id, dest_eui_64) PAE_SUPP_NOT_ENABLED
|
||||
#define ws_pae_supp_border_router_addr_write NULL
|
||||
#define ws_pae_supp_border_router_addr_read NULL
|
||||
#define ws_pae_supp_gtk_hash_update NULL
|
||||
#define ws_pae_supp_nw_key_index_update NULL
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "fhss_config.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_pae_timers.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
#define TRACE_GROUP "wspt"
|
||||
|
||||
#define SECONDS_IN_DAY 24 * 60 * 60
|
||||
#define SECONDS_IN_MONTH 30 * SECONDS_IN_DAY
|
||||
#define SECONDS_IN_MINUTE 60
|
||||
|
||||
#define DEFAULT_GTK_EXPIRE_OFFSET 43200 // 30 days
|
||||
#define DEFAULT_PMK_LIFETIME 4 // 4 months
|
||||
#define DEFAULT_PTK_LIFETIME 2 // 2 months
|
||||
#define DEFAULT_GTK_NEW_ACTIVATION_TIME 720 // default 1/720 * 30 days --> 60 minutes
|
||||
#define DEFAULT_REVOCATION_LIFETIME_REDUCTION 30 // default 1/30 * 30 days --> 1 day
|
||||
#define DEFAULT_GTK_REQUEST_IMIN 4 // 4 minutes
|
||||
#define DEFAULT_GTK_REQUEST_IMAX 64 // 64 minutes
|
||||
#define DEFAULT_GTK_MAX_MISMATCH 64 // 64 minutes
|
||||
#define DEFAULT_GTK_NEW_INSTALL_REQUIRED 80 // 80 percent of GTK lifetime --> 24 days
|
||||
|
||||
static void ws_pae_timers_calculate(timer_settings_t *timer_settings);
|
||||
|
||||
void ws_pae_timers_settings_init(timer_settings_t *timer_settings)
|
||||
{
|
||||
timer_settings->gtk_expire_offset = DEFAULT_GTK_EXPIRE_OFFSET * SECONDS_IN_MINUTE;
|
||||
timer_settings->pmk_lifetime = DEFAULT_PMK_LIFETIME * SECONDS_IN_MONTH;
|
||||
timer_settings->ptk_lifetime = DEFAULT_PTK_LIFETIME * SECONDS_IN_MONTH;
|
||||
timer_settings->gtk_new_act_time = DEFAULT_GTK_NEW_ACTIVATION_TIME;
|
||||
timer_settings->revocat_lifetime_reduct = DEFAULT_REVOCATION_LIFETIME_REDUCTION;
|
||||
timer_settings->gtk_request_imin = DEFAULT_GTK_REQUEST_IMIN * SECONDS_IN_MINUTE;
|
||||
timer_settings->gtk_request_imax = DEFAULT_GTK_REQUEST_IMAX * SECONDS_IN_MINUTE;
|
||||
timer_settings->gtk_max_mismatch = DEFAULT_GTK_MAX_MISMATCH * SECONDS_IN_MINUTE;
|
||||
timer_settings->gtk_new_install_req = DEFAULT_GTK_NEW_INSTALL_REQUIRED;
|
||||
}
|
||||
|
||||
void ws_pae_timers_lifetime_set(timer_settings_t *timer_settings, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime)
|
||||
{
|
||||
if (gtk_lifetime) {
|
||||
timer_settings->gtk_expire_offset = gtk_lifetime * 60;
|
||||
}
|
||||
if (pmk_lifetime) {
|
||||
timer_settings->pmk_lifetime = pmk_lifetime * 60;
|
||||
}
|
||||
if (ptk_lifetime) {
|
||||
timer_settings->ptk_lifetime = ptk_lifetime * 60;
|
||||
}
|
||||
ws_pae_timers_calculate(timer_settings);
|
||||
}
|
||||
|
||||
void ws_pae_timers_gtk_time_settings_set(timer_settings_t *timer_settings, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch)
|
||||
{
|
||||
if (revocat_lifetime_reduct) {
|
||||
timer_settings->revocat_lifetime_reduct = revocat_lifetime_reduct;
|
||||
}
|
||||
if (new_activation_time) {
|
||||
timer_settings->gtk_new_act_time = new_activation_time;
|
||||
}
|
||||
if (new_install_req) {
|
||||
timer_settings->gtk_new_install_req = new_install_req;
|
||||
}
|
||||
if (max_mismatch) {
|
||||
timer_settings->gtk_max_mismatch = max_mismatch * 60;
|
||||
}
|
||||
ws_pae_timers_calculate(timer_settings);
|
||||
}
|
||||
|
||||
static void ws_pae_timers_calculate(timer_settings_t *timer_settings)
|
||||
{
|
||||
// Calculate GTK_NEW_INSTALL_REQUIRED < 100 * (1 - 1 / REVOCATION_LIFETIME_REDUCTION)
|
||||
uint8_t calc_gtk_new_install_req = 100 - (100 / timer_settings->revocat_lifetime_reduct);
|
||||
|
||||
if (timer_settings->gtk_expire_offset < 3600) {
|
||||
// For very short GTKs give some more time to distribute the new GTK key to network, tune this if needed
|
||||
calc_gtk_new_install_req = calc_gtk_new_install_req * 60 / 100;
|
||||
}
|
||||
|
||||
if (timer_settings->gtk_new_install_req > calc_gtk_new_install_req) {
|
||||
tr_info("GTK new install required adjusted %i", calc_gtk_new_install_req);
|
||||
timer_settings->gtk_new_install_req = calc_gtk_new_install_req;
|
||||
}
|
||||
|
||||
// Verify that GTK request Imin and Imax are sensible when compared to revocation lifetime
|
||||
timer_settings->gtk_request_imin = DEFAULT_GTK_REQUEST_IMIN * SECONDS_IN_MINUTE;
|
||||
timer_settings->gtk_request_imax = DEFAULT_GTK_REQUEST_IMAX * SECONDS_IN_MINUTE;
|
||||
|
||||
uint32_t gtk_revocation_lifetime = timer_settings->gtk_expire_offset / timer_settings->revocat_lifetime_reduct;
|
||||
uint32_t new_activation_time = timer_settings->gtk_expire_offset / timer_settings->gtk_new_act_time;
|
||||
|
||||
uint32_t time_to_update = gtk_revocation_lifetime;
|
||||
if (gtk_revocation_lifetime > new_activation_time) {
|
||||
time_to_update = gtk_revocation_lifetime - new_activation_time;
|
||||
}
|
||||
|
||||
tr_info("Key timers revocation lifetime: %"PRIu32", new activation time: %"PRIu32", max mismatch %i, time to update: %"PRIu32"", gtk_revocation_lifetime, new_activation_time, timer_settings->gtk_max_mismatch, time_to_update);
|
||||
|
||||
// If time to update results smaller GTK request Imax use it for calculation otherwise use GTK max mismatch
|
||||
if (time_to_update < timer_settings->gtk_max_mismatch) {
|
||||
// If time to update is smaller than GTK request Imax update GTK request values
|
||||
if (timer_settings->gtk_request_imax > time_to_update) {
|
||||
timer_settings->gtk_request_imin = time_to_update / 4;
|
||||
timer_settings->gtk_request_imax = time_to_update / 2;
|
||||
tr_info("GTK request timers adjusted Imin: %i, Imax: %i", timer_settings->gtk_request_imin, timer_settings->gtk_request_imax);
|
||||
}
|
||||
} else if (timer_settings->gtk_request_imax > timer_settings->gtk_max_mismatch) {
|
||||
// If GTK request Imax is larger than GTK max mismatch update GTK request values
|
||||
|
||||
// For small GTK max mismatch times, scale the Imin to be larger than default 4 / 64;
|
||||
uint16_t scaler;
|
||||
if (timer_settings->gtk_max_mismatch < 50) {
|
||||
scaler = 10;
|
||||
} else if (timer_settings->gtk_max_mismatch > 600) {
|
||||
scaler = 1;
|
||||
} else {
|
||||
// About 1 minute mismatch, results 37 seconds Imin and 60 seconds Imax
|
||||
scaler = (600 - timer_settings->gtk_max_mismatch) / 54;
|
||||
}
|
||||
|
||||
timer_settings->gtk_request_imin = timer_settings->gtk_max_mismatch * scaler * DEFAULT_GTK_REQUEST_IMIN / DEFAULT_GTK_REQUEST_IMAX;
|
||||
timer_settings->gtk_request_imax = timer_settings->gtk_max_mismatch;
|
||||
tr_info("GTK request timers adjusted Imin: %i, Imax: %i", timer_settings->gtk_request_imin, timer_settings->gtk_request_imax);
|
||||
}
|
||||
}
|
||||
|
||||
bool ws_pae_timers_gtk_new_install_required(timer_settings_t *timer_settings, uint32_t seconds)
|
||||
{
|
||||
uint32_t gtk_new_install_req_seconds = timer_settings->gtk_expire_offset - timer_settings->gtk_new_install_req * timer_settings->gtk_expire_offset / 100;
|
||||
|
||||
if (seconds < gtk_new_install_req_seconds) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ws_pae_timers_gtk_new_activation_time(timer_settings_t *timer_settings, uint32_t seconds)
|
||||
{
|
||||
uint32_t gtk_gtk_new_activation_time_seconds = timer_settings->gtk_expire_offset / timer_settings->gtk_new_act_time;
|
||||
|
||||
if (seconds < gtk_gtk_new_activation_time_seconds) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ws_pae_timers_gtk_revocation_lifetime_get(timer_settings_t *timer_settings)
|
||||
{
|
||||
return timer_settings->gtk_expire_offset / timer_settings->revocat_lifetime_reduct;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_PAE_TIMERS_H_
|
||||
#define WS_PAE_TIMERS_H_
|
||||
|
||||
typedef struct {
|
||||
uint32_t gtk_expire_offset; // GTK lifetime; GTK_EXPIRE_OFFSET (seconds)
|
||||
uint32_t pmk_lifetime; // PMK lifetime (seconds)
|
||||
uint32_t ptk_lifetime; // PTK lifetime (seconds)
|
||||
uint16_t gtk_new_act_time; // GTK_NEW_ACTIVATION_TIME (1/X of expire offset)
|
||||
uint16_t revocat_lifetime_reduct; // REVOCATION_LIFETIME_REDUCTION (reduction of lifetime)
|
||||
uint16_t gtk_request_imin; // GTK_REQUEST_IMIN (seconds)
|
||||
uint16_t gtk_request_imax; // GTK_REQUEST_IMAX (seconds)
|
||||
uint16_t gtk_max_mismatch; // GTK_MAX_MISMATCH (seconds)
|
||||
uint8_t gtk_new_install_req; // GTK_NEW_INSTALL_REQUIRED (percent of GTK lifetime)
|
||||
} timer_settings_t;
|
||||
|
||||
/**
|
||||
* ws_pae_timers_settings_init initializes timer settings structure
|
||||
*
|
||||
* \param timer_settings timer settings
|
||||
*
|
||||
*/
|
||||
void ws_pae_timers_settings_init(timer_settings_t *timer_settings);
|
||||
|
||||
/**
|
||||
* ws_pae_timers_lifetime_set sets GTK, PTK and PTK lifetimes
|
||||
*
|
||||
* \param timer_settings timer settings
|
||||
* \param gtk_lifetime GTK lifetime
|
||||
* \param pmk_lifetime PMK lifetime
|
||||
* \param ptk_lifetime PTK lifetime
|
||||
*
|
||||
*/
|
||||
void ws_pae_timers_lifetime_set(timer_settings_t *timer_settings, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime);
|
||||
|
||||
/**
|
||||
* ws_pae_timers_gtk_time_settings_set sets GTK, PTK and PTK lifetimes
|
||||
*
|
||||
* \param timer_settings timer settings
|
||||
* \param revocat_lifetime_reduct revocation lifetime reduction
|
||||
* \param new_activation_time new activation time
|
||||
* \param new_install_req new install required
|
||||
* \param max_mismatch max mismatch
|
||||
*
|
||||
*/
|
||||
void ws_pae_timers_gtk_time_settings_set(timer_settings_t *timer_settings, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch);
|
||||
|
||||
/**
|
||||
* ws_pae_timers_gtk_new_install_required GTK new install required check
|
||||
*
|
||||
* \param timer_settings timer settings
|
||||
* \param seconds elapsed seconds
|
||||
*
|
||||
* \return true new GTK install required expired
|
||||
* \return false GTK install not required
|
||||
*
|
||||
*/
|
||||
bool ws_pae_timers_gtk_new_install_required(timer_settings_t *timer_settings, uint32_t seconds);
|
||||
|
||||
/**
|
||||
* ws_pae_timers_gtk_new_activation_time GTK new activation time
|
||||
*
|
||||
* \param timer_settings timer settings
|
||||
* \param seconds elapsed seconds
|
||||
*
|
||||
* \return true GTK new activation time expired
|
||||
* \return false GTK new activation time not expired
|
||||
*
|
||||
*/
|
||||
bool ws_pae_timers_gtk_new_activation_time(timer_settings_t *timer_settings, uint32_t seconds);
|
||||
|
||||
/**
|
||||
* ws_pae_timers_gtk_revocation_lifetime_get GTK revocation lifetime get
|
||||
*
|
||||
* \param timer_settings timer settings
|
||||
*
|
||||
* \return GTK revocation lifetime
|
||||
*
|
||||
*/
|
||||
uint32_t ws_pae_timers_gtk_revocation_lifetime_get(timer_settings_t *timer_settings);
|
||||
|
||||
#endif /* WS_PAE_TIMERS_H_ */
|
|
@ -25,6 +25,7 @@
|
|||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "randLIB.h"
|
||||
|
||||
#include "ns_trace.h"
|
||||
|
@ -60,7 +61,7 @@ int ws_test_gtk_set(int8_t interface_id, uint8_t *gtk[4])
|
|||
(void) interface_id;
|
||||
(void) gtk;
|
||||
|
||||
return 0;
|
||||
return ws_pae_controller_gtk_update(interface_id, gtk);
|
||||
}
|
||||
|
||||
int ws_test_active_key_set(int8_t interface_id, uint8_t index)
|
||||
|
@ -68,7 +69,7 @@ int ws_test_active_key_set(int8_t interface_id, uint8_t index)
|
|||
(void) interface_id;
|
||||
(void) index;
|
||||
|
||||
return 0;
|
||||
return ws_pae_controller_active_key_update(interface_id, index);
|
||||
}
|
||||
|
||||
int ws_test_key_lifetime_set(int8_t interface_id, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime)
|
||||
|
@ -78,17 +79,27 @@ int ws_test_key_lifetime_set(int8_t interface_id, uint32_t gtk_lifetime, uint32_
|
|||
(void) pmk_lifetime;
|
||||
(void) ptk_lifetime;
|
||||
|
||||
return 0;
|
||||
return ws_pae_controller_key_lifetime_update(interface_id, gtk_lifetime, pmk_lifetime, ptk_lifetime);
|
||||
}
|
||||
|
||||
int ws_test_gtk_time_settings_set(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint32_t max_mismatch)
|
||||
int ws_test_gtk_time_settings_set(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) revocat_lifetime_reduct;
|
||||
(void) new_activation_time;
|
||||
(void) new_install_req;
|
||||
(void) max_mismatch;
|
||||
|
||||
return 0;
|
||||
|
||||
return ws_pae_controller_gtk_time_settings_update(interface_id, revocat_lifetime_reduct, new_activation_time, new_install_req, max_mismatch);
|
||||
}
|
||||
|
||||
int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4])
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) gtk;
|
||||
|
||||
return ws_pae_controller_next_gtk_update(interface_id, gtk);
|
||||
}
|
||||
|
||||
#endif // HAVE_WS
|
||||
|
|
|
@ -325,12 +325,12 @@ static buffer_t *icmpv6_echo_request_handler(buffer_t *buf)
|
|||
|
||||
if (addr_is_ipv6_multicast(buf->dst_sa.address)) {
|
||||
const uint8_t *ipv6_ptr;
|
||||
memcpy(buf->dst_sa.address, buf->src_sa.address, 16);
|
||||
ipv6_ptr = addr_select_source(cur, buf->dst_sa.address, 0);
|
||||
if (!ipv6_ptr) {
|
||||
tr_debug("No address");
|
||||
return buffer_free(buf);
|
||||
}
|
||||
memcpy(buf->dst_sa.address, buf->src_sa.address, 16);
|
||||
memcpy(buf->src_sa.address, ipv6_ptr, 16);
|
||||
} else {
|
||||
memswap(buf->dst_sa.address, buf->src_sa.address, 16);
|
||||
|
@ -570,16 +570,8 @@ int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, const
|
|||
//Validate first current list If prefix is already defined adress
|
||||
ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) {
|
||||
if (e->source == ADDR_SOURCE_SLAAC && (e->prefix_len == prefix_len) && bitsequal(e->address, prefix_ptr, prefix_len)) {
|
||||
//Update Current lifetimes (see RFC 4862 for rules detail)
|
||||
if (valid_lifetime > (2 * 60 * 60) || valid_lifetime > e->valid_lifetime) {
|
||||
addr_set_valid_lifetime(cur, e, valid_lifetime);
|
||||
} else if (e->valid_lifetime <= (2 * 60 * 60)) {
|
||||
//NOT Update Valid Lifetime
|
||||
} else {
|
||||
addr_set_valid_lifetime(cur, e, 2 * 60 * 60);
|
||||
}
|
||||
|
||||
addr_set_preferred_lifetime(cur, e, preferred_lifetime);
|
||||
addr_lifetime_update(cur, e, valid_lifetime, preferred_lifetime, 2 * 60 * 60);
|
||||
ret_val = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1320,6 +1312,63 @@ uint8_t *icmpv6_write_mtu_option(uint32_t mtu, uint8_t *dptr)
|
|||
return dptr;
|
||||
}
|
||||
|
||||
void ack_receive_cb(struct buffer *buffer_ptr, uint8_t status)
|
||||
{
|
||||
/*icmpv6_na_handler functionality based on ACK*/
|
||||
ipv6_neighbour_t *neighbour_entry;
|
||||
uint8_t ll_target[16];
|
||||
|
||||
if (status != SOCKET_TX_DONE) {
|
||||
/*NS failed*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer_ptr->dst_sa.addr_type == ADDR_IPV6) {
|
||||
/*Full IPv6 address*/
|
||||
memcpy(ll_target, buffer_ptr->dst_sa.address, 16);
|
||||
} else if (buffer_ptr->dst_sa.addr_type == ADDR_802_15_4_LONG) {
|
||||
// Build link local address from long MAC address
|
||||
memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8);
|
||||
memcpy(ll_target + 8, &buffer_ptr->dst_sa.address[2], 8);
|
||||
ll_target[8] ^= 2;
|
||||
} else {
|
||||
tr_warn("wrong address %d %s", buffer_ptr->dst_sa.addr_type, trace_array(buffer_ptr->dst_sa.address, 16));
|
||||
return;
|
||||
}
|
||||
|
||||
neighbour_entry = ipv6_neighbour_lookup(&buffer_ptr->interface->ipv6_neighbour_cache, ll_target);
|
||||
if (neighbour_entry) {
|
||||
ipv6_neighbour_update_from_na(&buffer_ptr->interface->ipv6_neighbour_cache, neighbour_entry, NA_S, buffer_ptr->dst_sa.addr_type, buffer_ptr->dst_sa.address);
|
||||
}
|
||||
|
||||
if (ws_info(buffer_ptr->interface)) {
|
||||
ws_common_neighbor_update(buffer_ptr->interface, ll_target);
|
||||
}
|
||||
}
|
||||
void ack_remove_neighbour_cb(struct buffer *buffer_ptr, uint8_t status)
|
||||
{
|
||||
/*icmpv6_na_handler functionality based on ACK*/
|
||||
uint8_t ll_target[16];
|
||||
(void)status;
|
||||
|
||||
if (buffer_ptr->dst_sa.addr_type == ADDR_IPV6) {
|
||||
/*Full IPv6 address*/
|
||||
memcpy(ll_target, buffer_ptr->dst_sa.address, 16);
|
||||
} else if (buffer_ptr->dst_sa.addr_type == ADDR_802_15_4_LONG) {
|
||||
// Build link local address from long MAC address
|
||||
memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8);
|
||||
memcpy(ll_target + 8, &buffer_ptr->dst_sa.address[2], 8);
|
||||
ll_target[8] ^= 2;
|
||||
} else {
|
||||
tr_warn("wrong address %d %s", buffer_ptr->dst_sa.addr_type, trace_array(buffer_ptr->dst_sa.address, 16));
|
||||
return;
|
||||
}
|
||||
if (ws_info(buffer_ptr->interface)) {
|
||||
ws_common_neighbor_remove(buffer_ptr->interface, ll_target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t target_addr[16], const uint8_t *prompting_src_addr, bool unicast, bool unspecified_source, const aro_t *aro)
|
||||
{
|
||||
if (!cur || addr_is_ipv6_multicast(target_addr)) {
|
||||
|
@ -1394,10 +1443,15 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
|
|||
}
|
||||
/* If ARO Success sending is omitted, MAC ACK is used instead */
|
||||
/* Setting callback for receiving ACK from adaptation layer */
|
||||
if (aro && cur->ipv6_neighbour_cache.omit_aro_success) {
|
||||
if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success) {
|
||||
buf->ack_receive_cb = rpl_control_address_register_done;
|
||||
}
|
||||
}
|
||||
if (unicast && (!aro && cur->ipv6_neighbour_cache.omit_na)) {
|
||||
/*MAC ACK is processed as success response*/
|
||||
buf->ack_receive_cb = ack_receive_cb;
|
||||
}
|
||||
|
||||
buf->src_sa.addr_type = ADDR_IPV6;
|
||||
|
||||
/* NS packets are implicitly on-link. If we ever find ourselves sending an
|
||||
|
@ -1530,11 +1584,16 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
|
|||
|
||||
tr_debug("Build NA");
|
||||
|
||||
/* Check if ARO status == success, then sending can be omitted with flag */
|
||||
if (aro && cur->ipv6_neighbour_cache.omit_aro_success && aro->status == ARO_SUCCESS) {
|
||||
tr_debug("Omit success reply");
|
||||
/* Check if ARO response and status == success, then sending can be omitted with flag */
|
||||
if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success && aro->status == ARO_SUCCESS) {
|
||||
tr_debug("Omit NA ARO success");
|
||||
return NULL;
|
||||
}
|
||||
/* All other than ARO NA messages are omitted and MAC ACK is considered as success */
|
||||
if (!tllao_required && (!aro && cur->ipv6_neighbour_cache.omit_na)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
buffer_t *buf = buffer_get(8 + 16 + 16 + 16); /* fixed, target addr, target ll addr, aro */
|
||||
if (!buf) {
|
||||
|
@ -1616,6 +1675,11 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
|
|||
memcpy(ptr, aro->eui64, 8);
|
||||
ptr += 8;
|
||||
}
|
||||
if (ws_info(cur) && aro && aro->status != ARO_SUCCESS) {
|
||||
/*If Aro failed we will kill the neigbour after we have succeeded in sending message*/
|
||||
buf->ack_receive_cb = ack_remove_neighbour_cb;
|
||||
}
|
||||
|
||||
//Force Next Hop is destination
|
||||
ipv6_buffer_route_to(buf, buf->dst_sa.address, cur);
|
||||
|
||||
|
|
|
@ -35,9 +35,11 @@ prefix_entry_t *icmpv6_prefix_add(prefix_list_t *list, const uint8_t *prefixPtr,
|
|||
|
||||
entry = icmpv6_prefix_compare(list, prefixPtr, prefix_len);
|
||||
if (entry) {
|
||||
if (flags != 0xff) {
|
||||
entry->options = flags;
|
||||
entry->lifetime = lifeTime;
|
||||
entry->preftime = prefTime;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ void addr_fast_timer(struct protocol_interface_info_entry *cur, uint_fast16_t ti
|
|||
void addr_slow_timer(struct protocol_interface_info_entry *cur, uint_fast16_t seconds);
|
||||
struct if_address_entry *addr_add(struct protocol_interface_info_entry *cur, const uint8_t address[__static 16], uint_fast8_t prefix_len, if_address_source_t source, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad);
|
||||
int_fast8_t addr_delete(struct protocol_interface_info_entry *cur, const uint8_t address[__static 16]);
|
||||
int_fast8_t addr_deprecate(struct protocol_interface_info_entry *cur, const uint8_t address[__static 16]);
|
||||
void addr_delete_matching(struct protocol_interface_info_entry *cur, const uint8_t *prefix, uint8_t prefix_len, if_address_source_t source);
|
||||
void addr_delete_entry(struct protocol_interface_info_entry *cur, if_address_entry_t *addr);
|
||||
void addr_set_non_preferred(struct protocol_interface_info_entry *cur, if_address_source_t source);
|
||||
|
@ -166,6 +167,8 @@ void addr_cb(struct protocol_interface_info_entry *interface, if_address_entry_t
|
|||
void addr_set_valid_lifetime(struct protocol_interface_info_entry *interface, if_address_entry_t *entry, uint32_t valid_lifetime);
|
||||
void addr_set_preferred_lifetime(struct protocol_interface_info_entry *interface, if_address_entry_t *entry, uint32_t preferred_lifetime);
|
||||
|
||||
void addr_lifetime_update(struct protocol_interface_info_entry *interface, if_address_entry_t *address, uint32_t valid_lifetime, uint32_t preferred_lifetime, uint32_t threshold);
|
||||
|
||||
int_fast8_t addr_policy_table_add_entry(const uint8_t *prefix, uint8_t len, uint8_t precedence, uint8_t label);
|
||||
int_fast8_t addr_policy_table_delete_entry(const uint8_t *prefix, uint8_t len);
|
||||
uint8_t addr_len_from_type(addrtype_t addr_type);
|
||||
|
@ -178,6 +181,8 @@ struct if_address_entry *addr_get_entry(const struct protocol_interface_info_ent
|
|||
bool addr_is_assigned_to_interface(const struct protocol_interface_info_entry *interface, const uint8_t addr[__static 16]);
|
||||
bool addr_is_tentative_for_interface(const struct protocol_interface_info_entry *interface, const uint8_t addr[__static 16]);
|
||||
|
||||
void addr_policy_remove_by_label(uint8_t label);
|
||||
|
||||
void addr_duplicate_detected(struct protocol_interface_info_entry *interface, const uint8_t addr[__static 16]);
|
||||
|
||||
struct if_group_entry *addr_add_group(struct protocol_interface_info_entry *interface, const uint8_t group[__static 16]);
|
||||
|
|
|
@ -690,6 +690,13 @@ const uint8_t *addr_select_source(protocol_interface_info_entry_t *interface, co
|
|||
}
|
||||
}
|
||||
|
||||
/* Rule 9 select most precated one */
|
||||
if (policy_SA->precedence > policy_SB->precedence) {
|
||||
PREFER_SA;
|
||||
} else if (policy_SB->precedence > policy_SA->precedence) {
|
||||
PREFER_SB;
|
||||
}
|
||||
|
||||
/* Tie */
|
||||
PREFER_SA;
|
||||
}
|
||||
|
@ -858,6 +865,7 @@ void addr_fast_timer(protocol_interface_info_entry_t *cur, uint_fast16_t ticks)
|
|||
}
|
||||
#endif
|
||||
} else {
|
||||
addr->addr_reg_done = 0;
|
||||
addr_cb(cur, addr, ADDR_CALLBACK_TIMER);
|
||||
}
|
||||
|
||||
|
@ -1002,6 +1010,19 @@ int_fast8_t addr_delete(protocol_interface_info_entry_t *cur, const uint8_t addr
|
|||
return -1;
|
||||
}
|
||||
|
||||
int_fast8_t addr_deprecate(protocol_interface_info_entry_t *cur, const uint8_t address[static 16])
|
||||
{
|
||||
ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
|
||||
if (memcmp(e->address, address, 16) == 0) {
|
||||
tr_debug("Deprecate address %s", trace_ipv6(e->address));
|
||||
addr_lifetime_update(cur, e, 0, 0, 30 * 60); //Accept max 30 min lifetime
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void addr_delete_matching(protocol_interface_info_entry_t *cur, const uint8_t *prefix, uint8_t prefix_len, if_address_source_t source)
|
||||
{
|
||||
ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) {
|
||||
|
@ -1091,6 +1112,20 @@ void addr_set_preferred_lifetime(protocol_interface_info_entry_t *interface, if_
|
|||
}
|
||||
}
|
||||
|
||||
void addr_lifetime_update(protocol_interface_info_entry_t *interface, if_address_entry_t *address, uint32_t valid_lifetime, uint32_t preferred_lifetime, uint32_t threshold)
|
||||
{
|
||||
//Update Current lifetimes (see RFC 4862 for rules detail)
|
||||
if (valid_lifetime > threshold || valid_lifetime > address->valid_lifetime) {
|
||||
addr_set_valid_lifetime(interface, address, valid_lifetime);
|
||||
} else if (address->valid_lifetime <= threshold) {
|
||||
//NOT Update Valid Lifetime
|
||||
} else {
|
||||
addr_set_valid_lifetime(interface, address, threshold);
|
||||
}
|
||||
|
||||
addr_set_preferred_lifetime(interface, address, preferred_lifetime);
|
||||
}
|
||||
|
||||
void memswap(uint8_t *restrict a, uint8_t *restrict b, uint_fast8_t len)
|
||||
{
|
||||
while (len--) {
|
||||
|
@ -1398,6 +1433,21 @@ int8_t addr_interface_select_source(protocol_interface_info_entry_t *cur, uint8_
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
void addr_policy_remove_by_label(uint8_t label)
|
||||
{
|
||||
ns_list_foreach_safe(addr_policy_table_entry_t, entry, &addr_policy_table) {
|
||||
if (entry->label == label) {
|
||||
/*
|
||||
* Remove label policy if no local address matches"
|
||||
*/
|
||||
if (!protocol_interface_any_address_match(entry->prefix, entry->prefix_len)) {
|
||||
ns_list_remove(&addr_policy_table, entry);
|
||||
ns_dyn_mem_free(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This last function must always be compiled with tracing enabled
|
||||
#ifndef FEA_TRACE_SUPPORT
|
||||
#define FEA_TRACE_SUPPORT 1
|
||||
|
|
|
@ -272,7 +272,7 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds)
|
|||
* /param guaPrefix Prefix which will be removed
|
||||
* /param delete_gua_addresses Whether or not assigned addresses with the prefix should be removed from the interface.
|
||||
*/
|
||||
void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16], bool delete_gua_addresses)
|
||||
void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], bool delete_gua_addresses)
|
||||
{
|
||||
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
|
||||
if (serverInfo) {
|
||||
|
@ -390,7 +390,7 @@ int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], u
|
|||
|
||||
return -1;
|
||||
}
|
||||
void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16], bool delete_gua_addresses)
|
||||
void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], bool delete_gua_addresses)
|
||||
{
|
||||
(void) interface;
|
||||
(void) guaPrefix;
|
||||
|
|
|
@ -54,7 +54,7 @@ void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[stat
|
|||
* /param guaPrefix Prefix which will be removed
|
||||
* /param delete_gua_addresses Whether or not assigned addresses with the prefix should be removed from the interface.
|
||||
*/
|
||||
void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16], bool delete_gua_addresses);
|
||||
void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], bool delete_gua_addresses);
|
||||
|
||||
|
||||
void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds);
|
||||
|
|
|
@ -38,9 +38,12 @@ void dhcp_client_init(int8_t interface);
|
|||
|
||||
/* Set configurations for DHCP client
|
||||
*
|
||||
* /param interface Client Inteface ID
|
||||
* /param renew_uses_solicit Instead of renew message SOLICIT is used.
|
||||
* /param one_client_for_this_interface True Interface use oneinstance for allocate address
|
||||
* /param no_address_hint IAID use address at Solicit
|
||||
*/
|
||||
void dhcp_client_configure(int8_t interface, bool renew_uses_solicit);
|
||||
void dhcp_client_configure(int8_t interface, bool renew_uses_solicit, bool one_client_for_this_interface, bool no_address_hint);
|
||||
|
||||
/* Set Timeout parameters for SOLICIT transactions
|
||||
*
|
||||
|
@ -92,11 +95,13 @@ void dhcp_client_global_address_renew(int8_t interface);
|
|||
* /param prefix dhcp server ML16 address where address is registered.
|
||||
*
|
||||
*/
|
||||
void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]);
|
||||
void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uint8_t prefix[static 16]);
|
||||
|
||||
|
||||
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]);
|
||||
|
||||
int dhcp_client_server_address_update(int8_t interface, uint8_t prefix[static 16], uint8_t server_address[static 16]);
|
||||
|
||||
|
||||
|
||||
#endif /* DHCPV6_CLIENT_API_H_ */
|
||||
|
|
|
@ -41,11 +41,14 @@ typedef struct {
|
|||
uint8_t libDhcp_instance;
|
||||
int8_t interface;
|
||||
bool renew_uses_solicit: 1;
|
||||
bool one_instance_interface: 1;
|
||||
bool no_address_hint: 1;
|
||||
} dhcp_client_class_t;
|
||||
|
||||
static dhcp_client_class_t dhcp_client;
|
||||
|
||||
void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr);
|
||||
static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr);
|
||||
void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason);
|
||||
|
||||
|
||||
void dhcp_client_init(int8_t interface)
|
||||
|
@ -57,14 +60,19 @@ void dhcp_client_init(int8_t interface)
|
|||
dhcp_client.sol_timeout = 0;
|
||||
dhcp_client.sol_max_rt = 0;
|
||||
dhcp_client.sol_max_rc = 0;
|
||||
dhcp_client.renew_uses_solicit = false;
|
||||
dhcp_client.one_instance_interface = false;
|
||||
dhcp_client.no_address_hint = false;
|
||||
|
||||
return;
|
||||
}
|
||||
void dhcp_client_configure(int8_t interface, bool renew_uses_solicit)
|
||||
void dhcp_client_configure(int8_t interface, bool renew_uses_solicit, bool one_client_for_this_interface, bool no_address_hint)
|
||||
{
|
||||
// Set true if RENEW is not used and SOLICIT sent instead.
|
||||
(void)interface;
|
||||
dhcp_client.renew_uses_solicit = renew_uses_solicit;
|
||||
dhcp_client.one_instance_interface = one_client_for_this_interface;
|
||||
dhcp_client.no_address_hint = no_address_hint;
|
||||
}
|
||||
|
||||
void dhcp_client_solicit_timeout_set(int8_t interface, uint16_t timeout, uint16_t max_rt, uint8_t max_rc)
|
||||
|
@ -170,6 +178,14 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
|
|||
goto error_exit;
|
||||
}
|
||||
|
||||
if (dhcp_client.one_instance_interface && memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, dhcp_ia_non_temporal_params.nonTemporalAddress, 16)) {
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(dhcp_client.interface);
|
||||
if (cur) {
|
||||
addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(srv_data_ptr->iaNontemporalAddress.addressPrefix, dhcp_ia_non_temporal_params.nonTemporalAddress, 16);
|
||||
srv_data_ptr->iaNontemporalAddress.preferredTime = dhcp_ia_non_temporal_params.preferredValidLifeTime;
|
||||
srv_data_ptr->iaNontemporalAddress.validLifetime = dhcp_ia_non_temporal_params.validLifeTime;
|
||||
|
@ -177,13 +193,13 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
|
|||
srv_data_ptr->serverLinkType = serverId.linkType;
|
||||
srv_data_ptr->T0 = dhcp_ia_non_temporal_params.T0;
|
||||
srv_data_ptr->T1 = dhcp_ia_non_temporal_params.T1;
|
||||
srv_data_ptr->iaNonTemporalStructValid = true;
|
||||
|
||||
dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr);
|
||||
|
||||
bool status = dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr);
|
||||
|
||||
|
||||
if (dhcp_client.global_address_cb) {
|
||||
dhcp_client.global_address_cb(dhcp_client.interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, true);
|
||||
dhcp_client.global_address_cb(dhcp_client.interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, status);
|
||||
}
|
||||
return RET_MSG_ACCEPTED;
|
||||
error_exit:
|
||||
|
@ -198,20 +214,36 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
uint8_t *payload_ptr;
|
||||
uint32_t payload_len;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr;
|
||||
bool add_prefix;
|
||||
|
||||
if (mac64 == NULL || dhcp_addr == NULL) {
|
||||
tr_error("Invalid parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!prefix) {
|
||||
if (!prefix || dhcp_client.one_instance_interface) {
|
||||
//NULL Definition will only check That Interface is not generated
|
||||
if (libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client.libDhcp_instance)) {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client.libDhcp_instance);
|
||||
if (srv_data_ptr) {
|
||||
//Already Created to same interface
|
||||
if (dhcp_client.one_instance_interface && prefix) {
|
||||
if (srv_data_ptr->iaNonTemporalStructValid) {
|
||||
if (memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, prefix, 8)) {
|
||||
//Request new address direct from Server if prefix is new
|
||||
srv_data_ptr->iaNonTemporalStructValid = false;
|
||||
dhcpv6_renew(protocol_stack_interface_info_get_by_id(interface), NULL, ADDR_CALLBACK_TIMER);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} else if (dhcp_client_server_address_update(interface, prefix, dhcp_addr) == 0) {
|
||||
//No need for allocate new
|
||||
return 0;
|
||||
}
|
||||
|
||||
tr_debug("GEN new Dhcpv6 client %u", dhcp_client.libDhcp_instance);
|
||||
srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client.libDhcp_instance, mac64, link_type, prefix, dhcp_addr);
|
||||
|
||||
if (!srv_data_ptr) {
|
||||
|
@ -219,7 +251,15 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
return -1;
|
||||
}
|
||||
|
||||
payload_len = libdhcpv6_solication_message_length(link_type, prefix != NULL, 0);
|
||||
|
||||
if (!prefix || dhcp_client.no_address_hint) {
|
||||
add_prefix = false;
|
||||
} else {
|
||||
add_prefix = prefix != NULL;
|
||||
}
|
||||
|
||||
payload_len = libdhcpv6_solication_message_length(link_type, add_prefix, 0);
|
||||
|
||||
|
||||
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
|
||||
if (!payload_ptr) {
|
||||
|
@ -238,7 +278,7 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
solPacket.transActionId = libdhcpv6_txid_get();
|
||||
/*Non Temporal Address */
|
||||
|
||||
if (prefix) {
|
||||
if (prefix && !dhcp_client.no_address_hint) {
|
||||
dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
|
||||
nonTemporalAddress.requestedAddress = prefix;
|
||||
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &solPacket, &nonTemporalAddress, NULL);
|
||||
|
@ -253,6 +293,7 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
|
||||
return -1;
|
||||
}
|
||||
srv_data_ptr->iaNonTemporalStructValid = false;
|
||||
if (dhcp_client.sol_timeout != 0) {
|
||||
// Default retry values are modified from specification update to message
|
||||
dhcp_service_set_retry_timers(srv_data_ptr->transActionId, dhcp_client.sol_timeout, dhcp_client.sol_max_rt, dhcp_client.sol_max_rc);
|
||||
|
@ -261,13 +302,44 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_client_server_address_update(int8_t interface, uint8_t prefix[static 16], uint8_t server_address[static 16])
|
||||
{
|
||||
dhcpv6_client_server_data_t *srv_data_ptr = NULL;
|
||||
|
||||
if (dhcp_client.interface != interface) {
|
||||
tr_debug("Interface not match");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
|
||||
} else if (dhcp_client.one_instance_interface) {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client.libDhcp_instance);
|
||||
}
|
||||
if (!srv_data_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(srv_data_ptr->server_address, server_address, 16) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(srv_data_ptr->server_address, server_address, 16);
|
||||
if (!srv_data_ptr->iaNonTemporalStructValid) {
|
||||
dhcp_service_update_server_address(srv_data_ptr->transActionId, server_address);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dhcp_client_global_address_renew(int8_t interface)
|
||||
{
|
||||
(void)interface;
|
||||
return;
|
||||
}
|
||||
|
||||
void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16])
|
||||
void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uint8_t prefix[static 16])
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr;
|
||||
|
@ -276,33 +348,35 @@ void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[stati
|
|||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
|
||||
cur = protocol_stack_interface_info_get_by_id(interface);
|
||||
|
||||
do {
|
||||
if (cur == NULL || srv_data_ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
|
||||
tr_debug("Deleting address: %s", trace_ipv6(srv_data_ptr->iaNontemporalAddress.addressPrefix));
|
||||
|
||||
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
|
||||
if (dhcp_client.one_instance_interface) {
|
||||
addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
} else {
|
||||
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
}
|
||||
|
||||
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
|
||||
} while (srv_data_ptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason)
|
||||
{
|
||||
dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
|
||||
|
||||
dhcp_link_options_params_t serverLink;
|
||||
uint8_t *payload_ptr;
|
||||
uint32_t payload_len;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface->id, addr->address);
|
||||
dhcpv6_client_server_data_t *srv_data_ptr;
|
||||
if (addr) {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface->id, addr->address);
|
||||
} else {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client.libDhcp_instance);
|
||||
}
|
||||
|
||||
if (srv_data_ptr == NULL) {
|
||||
tr_warn("Dhcp address lost");
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
if (reason == ADDR_CALLBACK_INVALIDATED) {
|
||||
dhcp_service_req_remove(srv_data_ptr->transActionId);//stop retransmissions of renew
|
||||
|
@ -315,10 +389,12 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
|
|||
return;
|
||||
}
|
||||
|
||||
payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0);
|
||||
payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0, !dhcp_client.no_address_hint);
|
||||
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
|
||||
if (payload_ptr == NULL) {
|
||||
if (addr) {
|
||||
addr->state_timer = 200; //Retry after 20 seconds
|
||||
}
|
||||
tr_error("Out of memory");
|
||||
return ;
|
||||
}
|
||||
|
@ -337,18 +413,33 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
|
|||
packetReq.messageType = DHCPV6_SOLICATION_TYPE;
|
||||
}
|
||||
|
||||
|
||||
serverLink.linkID = srv_data_ptr->serverLinkId;
|
||||
serverLink.linkType = srv_data_ptr->serverLinkType;
|
||||
if (dhcp_client.no_address_hint && dhcp_client.renew_uses_solicit) {
|
||||
packetReq.timerT0 = 0;
|
||||
packetReq.timerT1 = 0;
|
||||
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, NULL, &serverLink);
|
||||
} else {
|
||||
// Set Address information
|
||||
dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
|
||||
nonTemporalAddress.requestedAddress = srv_data_ptr->iaNontemporalAddress.addressPrefix;
|
||||
nonTemporalAddress.preferredLifeTime = srv_data_ptr->iaNontemporalAddress.preferredTime;
|
||||
nonTemporalAddress.validLifeTime = srv_data_ptr->iaNontemporalAddress.validLifetime;
|
||||
serverLink.linkID = srv_data_ptr->serverLinkId;
|
||||
serverLink.linkType = srv_data_ptr->serverLinkType;
|
||||
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, &nonTemporalAddress, &serverLink);
|
||||
}
|
||||
// send solicit
|
||||
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr, srv_data_ptr->server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb);
|
||||
uint8_t *server_address = dhcp_service_relay_global_addres_get(dhcp_client.relay_instance);
|
||||
if (!server_address) {
|
||||
server_address = srv_data_ptr->server_address;
|
||||
}
|
||||
|
||||
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr, server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb);
|
||||
if (srv_data_ptr->transActionId == 0) {
|
||||
ns_dyn_mem_free(payload_ptr);
|
||||
if (addr) {
|
||||
addr->state_timer = 200; //Retry after 20 seconds
|
||||
}
|
||||
tr_error("DHCP renew send failed");
|
||||
}
|
||||
if (packetReq.messageType == DHCPV6_SOLICATION_TYPE && dhcp_client.sol_timeout != 0) {
|
||||
|
@ -357,7 +448,7 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
|
|||
}
|
||||
}
|
||||
|
||||
void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr)
|
||||
static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = NULL;
|
||||
if_address_entry_t *address_entry = NULL;
|
||||
|
@ -365,10 +456,11 @@ void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t
|
|||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
renewTimer = libdhcpv6_renew_time_define(srv_data_ptr);
|
||||
|
||||
srv_data_ptr->iaNonTemporalStructValid = true;
|
||||
address_entry = addr_get_entry(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
if (address_entry == NULL) {
|
||||
// create new
|
||||
|
@ -380,8 +472,10 @@ void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t
|
|||
|
||||
if (address_entry == NULL) {
|
||||
tr_error("Address add failed");
|
||||
return;
|
||||
srv_data_ptr->iaNonTemporalStructValid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (renewTimer) {
|
||||
// translate seconds to 100ms ticks
|
||||
if (renewTimer < 0xffffffff / 10) {
|
||||
|
@ -392,6 +486,7 @@ void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t
|
|||
}
|
||||
address_entry->state_timer = renewTimer;
|
||||
address_entry->cb = dhcpv6_renew;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -192,6 +192,7 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
unsigned macCurrentBE: 4;
|
||||
uint8_t macMaxCSMABackoffs;
|
||||
uint8_t backoff_period_in_10us; // max 2550us - it's 320us for standard 250kbps
|
||||
uint8_t mac_frame_filters;
|
||||
/* MAC channel parameters */
|
||||
channel_list_s mac_channel_list;
|
||||
uint8_t scan_duration; //Needed???
|
||||
|
@ -219,6 +220,8 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
uint16_t mac_ack_wait_duration;
|
||||
uint8_t mac_mlme_retry_max;
|
||||
uint8_t aUnitBackoffPeriod;
|
||||
uint8_t number_of_csma_ca_periods; /**< Number of CSMA-CA periods */
|
||||
uint16_t multi_cca_interval; /**< Length of the additional CSMA-CA period(s) in microseconds */
|
||||
/* Indirect queue parameters */
|
||||
struct mac_pre_build_frame *indirect_pd_data_request_queue;
|
||||
arm_event_t mac_mcps_timer_event;
|
||||
|
|
|
@ -267,6 +267,9 @@ const uint8_t *mac_header_parse_fcf_dsn(mac_fcf_sequence_t *header, const uint8_
|
|||
} else {
|
||||
header->DSN = 0;
|
||||
}
|
||||
//Check PanID presents at header
|
||||
header->DstPanPresents = mac_dst_panid_present(header);
|
||||
header->SrcPanPresents = mac_src_panid_present(header);
|
||||
return ptr;
|
||||
|
||||
}
|
||||
|
|
|
@ -362,8 +362,6 @@ static int8_t mac_virtual_data_req_handler(protocol_interface_rf_mac_setup_s *rf
|
|||
}
|
||||
|
||||
mac_header_parse_fcf_dsn(&buffer->fcf_dsn, data_ptr);
|
||||
buffer->fcf_dsn.DstPanPresents = mac_dst_panid_present(&buffer->fcf_dsn);
|
||||
buffer->fcf_dsn.SrcPanPresents = mac_src_panid_present(&buffer->fcf_dsn);
|
||||
// Use MAC sequence as handle
|
||||
buffer->msduHandle = buffer->fcf_dsn.DSN;
|
||||
memcpy(buffer->mac_payload, data_ptr, data_length);
|
||||
|
@ -982,11 +980,6 @@ static void mac_data_interface_frame_handler(mac_pre_parsed_frame_t *buf)
|
|||
mcps_sap_pre_parsed_frame_buffer_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mac_filter_modify_link_quality(rf_mac_setup->mac_interface_id, buf) == 1) {
|
||||
mcps_sap_pre_parsed_frame_buffer_free(buf);
|
||||
return;
|
||||
}
|
||||
/* push data to stack if sniffer mode is enabled */
|
||||
if (rf_mac_setup->macProminousMode) {
|
||||
mac_nap_tun_data_handler(buf, rf_mac_setup);
|
||||
|
@ -1423,13 +1416,20 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr,
|
|||
// FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted
|
||||
if ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL)) {
|
||||
if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype)) == true) {
|
||||
|
||||
if (rf_ptr->mac_tx_result == MAC_TX_FAIL) {
|
||||
buffer->fhss_retry_count += 1 + rf_ptr->mac_tx_status.retry;
|
||||
} else {
|
||||
buffer->fhss_retry_count += rf_ptr->mac_tx_status.retry;
|
||||
}
|
||||
buffer->fhss_cca_retry_count += rf_ptr->mac_tx_status.cca_cnt;
|
||||
mcps_sap_pd_req_queue_write(rf_ptr, buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
confirm.cca_retries = rf_ptr->mac_tx_status.cca_cnt;
|
||||
confirm.tx_retries = rf_ptr->mac_tx_status.retry;
|
||||
confirm.cca_retries = rf_ptr->mac_tx_status.cca_cnt + buffer->fhss_cca_retry_count;
|
||||
confirm.tx_retries = rf_ptr->mac_tx_status.retry + buffer->fhss_retry_count;
|
||||
mac_common_data_confirmation_handle(rf_ptr, buffer);
|
||||
confirm.msduHandle = buffer->msduHandle;
|
||||
confirm.status = buffer->status;
|
||||
|
@ -1600,9 +1600,8 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload, uint32_t rx_time)
|
||||
int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload)
|
||||
{
|
||||
(void)rx_time;
|
||||
phy_device_driver_s *dev_driver = rf_ptr->dev_driver->phy_driver;
|
||||
dev_driver_tx_buffer_s *tx_buf = &rf_ptr->dev_driver_tx_buffer;
|
||||
|
||||
|
@ -1740,7 +1739,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
|
|||
rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t *) &csma_params);
|
||||
if (rf_ptr->active_pd_data_request) {
|
||||
timer_mac_stop(rf_ptr);
|
||||
mac_pd_sap_set_phy_tx_time(rf_ptr, 0, false);
|
||||
mac_pd_abort_active_tx(rf_ptr);
|
||||
}
|
||||
return mcps_pd_data_cca_trig(rf_ptr, buffer);
|
||||
}
|
||||
|
@ -1828,6 +1827,13 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m
|
|||
}
|
||||
cca_enabled = true;
|
||||
}
|
||||
// Use double CCA check with FHSS for data packets only
|
||||
if (rf_ptr->fhss_api && !rf_ptr->mac_ack_tx_active && !rf_ptr->active_pd_data_request->asynch_request) {
|
||||
if ((buffer->tx_time - (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1))) > mac_mcps_sap_get_phy_timestamp(rf_ptr)) {
|
||||
buffer->csma_periods_left = rf_ptr->number_of_csma_ca_periods - 1;
|
||||
buffer->tx_time -= (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1));
|
||||
}
|
||||
}
|
||||
mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled);
|
||||
if (mac_plme_cca_req(rf_ptr) != 0) {
|
||||
if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) {
|
||||
|
|
|
@ -57,6 +57,11 @@ typedef enum {
|
|||
#define MAC_SAP_TRIG_TX 7
|
||||
#define MCPS_SAP_DATA_ACK_CNF_EVENT 8
|
||||
|
||||
// Default number of CSMA-CA periods
|
||||
#define MAC_DEFAULT_NUMBER_OF_CSMA_PERIODS 1
|
||||
// Interval between two CCA checks
|
||||
#define MAC_DEFAULT_CSMA_MULTI_CCA_INTERVAL 1000
|
||||
|
||||
/**
|
||||
* @brief struct mac_aux_security_header_t MAC auxiliarity security header structure
|
||||
* INTERNAL use only
|
||||
|
@ -126,6 +131,9 @@ typedef struct mac_pre_build_frame {
|
|||
uint8_t *mac_payload;
|
||||
uint8_t status;
|
||||
uint8_t asynch_channel;
|
||||
uint8_t csma_periods_left;
|
||||
uint8_t fhss_retry_count;
|
||||
uint8_t fhss_cca_retry_count;
|
||||
uint32_t tx_time;
|
||||
bool upper_layer_request;
|
||||
bool mac_allocated_payload_ptr: 1;
|
||||
|
@ -206,6 +214,6 @@ uint8_t mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_ma
|
|||
|
||||
int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer);
|
||||
|
||||
int8_t mcps_generic_ack_build(struct protocol_interface_rf_mac_setup *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload, uint32_t rx_time);
|
||||
int8_t mcps_generic_ack_build(struct protocol_interface_rf_mac_setup *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload);
|
||||
|
||||
#endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */
|
||||
|
|
|
@ -582,7 +582,7 @@ static int8_t mac_mlme_8bit_set(protocol_interface_rf_mac_setup_s *rf_mac_setup,
|
|||
break;
|
||||
|
||||
case macMinBE:
|
||||
if (value > rf_mac_setup->macMaxBE) {
|
||||
if (value < rf_mac_setup->macMaxBE) {
|
||||
rf_mac_setup->macMinBE = value;
|
||||
}
|
||||
break;
|
||||
|
@ -724,6 +724,16 @@ static int8_t mac_mlme_handle_set_values(protocol_interface_rf_mac_setup_s *rf_m
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int8_t mac_mlme_set_multi_csma_parameters(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
|
||||
{
|
||||
mlme_multi_csma_ca_param_t multi_csma_params;
|
||||
memcpy(&multi_csma_params, set_req->value_pointer, sizeof(mlme_multi_csma_ca_param_t));
|
||||
rf_mac_setup->multi_cca_interval = multi_csma_params.multi_cca_interval;
|
||||
rf_mac_setup->number_of_csma_ca_periods = multi_csma_params.number_of_csma_ca_periods;
|
||||
tr_debug("Multi CSMA-CA, interval: %u, periods %u", rf_mac_setup->multi_cca_interval, rf_mac_setup->number_of_csma_ca_periods);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
|
||||
{
|
||||
if (!set_req || !rf_mac_setup || !rf_mac_setup->dev_driver || !rf_mac_setup->dev_driver->phy_driver) {
|
||||
|
@ -749,6 +759,8 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
|
|||
memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8);
|
||||
}
|
||||
return 0;
|
||||
case macMultiCSMAParameters:
|
||||
return mac_mlme_set_multi_csma_parameters(rf_mac_setup, set_req);
|
||||
case macRfConfiguration:
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_RF_CONFIGURATION, (uint8_t *) set_req->value_pointer);
|
||||
mac_mlme_set_symbol_rate(rf_mac_setup);
|
||||
|
@ -1072,6 +1084,8 @@ protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, a
|
|||
entry->mac_interface_id = -1;
|
||||
entry->dev_driver = dev_driver;
|
||||
entry->aUnitBackoffPeriod = 20; //This can be different in some Platform 20 comes from 12-symbol turnaround and 8 symbol CCA read
|
||||
entry->number_of_csma_ca_periods = MAC_DEFAULT_NUMBER_OF_CSMA_PERIODS;
|
||||
entry->multi_cca_interval = MAC_DEFAULT_CSMA_MULTI_CCA_INTERVAL;
|
||||
|
||||
if (mac_sec_mib_init(entry, storage_sizes) != 0) {
|
||||
mac_mlme_data_base_deallocate(entry);
|
||||
|
@ -1140,6 +1154,10 @@ protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, a
|
|||
bool rf_support = false;
|
||||
dev_driver->phy_driver->extension(PHY_EXTENSION_DYNAMIC_RF_SUPPORTED, (uint8_t *)&rf_support);
|
||||
entry->rf_csma_extension_supported = rf_support;
|
||||
dev_driver->phy_driver->extension(PHY_EXTENSION_FILTERING_SUPPORT, (uint8_t *)&entry->mac_frame_filters);
|
||||
if (entry->mac_frame_filters & (1 << MAC_FRAME_VERSION_2)) {
|
||||
tr_debug("PHY supports 802.15.4-2015 frame filtering");
|
||||
}
|
||||
mac_mlme_set_symbol_rate(entry);
|
||||
|
||||
//How many 10us ticks backoff period is for waiting 20symbols which is typically 10 bytes time
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
// Measured 3750us with 1280 byte secured packet from calculating TX time to starting CSMA timer on PHY.
|
||||
// Typically varies from 500us to several milliseconds depending on packet size and the platform.
|
||||
// MAC should learn and make this dynamic by sending first few packets with predefined CSMA period.
|
||||
#define MIN_FHSS_CSMA_PERIOD_US 4000
|
||||
#define MIN_FHSS_CSMA_PERIOD_US 5000
|
||||
|
||||
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
|
||||
static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr);
|
||||
|
@ -83,6 +83,10 @@ void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
|||
|
||||
uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
||||
{
|
||||
// Use minimum allowed CSMA-CA for asynch frames
|
||||
if (rf_mac_setup->active_pd_data_request->asynch_request) {
|
||||
return MIN_FHSS_CSMA_PERIOD_US;
|
||||
}
|
||||
uint8_t backoff = mac_csma_random_backoff_get(rf_mac_setup);
|
||||
uint32_t backoff_in_us;
|
||||
//Multiple aUnitBackoffPeriod symbol time
|
||||
|
@ -101,6 +105,13 @@ uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
|||
if (backoff_in_us < MIN_FHSS_CSMA_PERIOD_US) {
|
||||
backoff_in_us += MIN_FHSS_CSMA_PERIOD_US;
|
||||
}
|
||||
// Backoff must be long enough to make multiple CCA checks
|
||||
if (backoff_in_us < (uint32_t)(rf_mac_setup->multi_cca_interval * (rf_mac_setup->number_of_csma_ca_periods - 1))) {
|
||||
backoff_in_us += ((rf_mac_setup->multi_cca_interval * (rf_mac_setup->number_of_csma_ca_periods - 1)) - backoff_in_us);
|
||||
}
|
||||
if (rf_mac_setup->mac_tx_retry) {
|
||||
backoff_in_us += rf_mac_setup->fhss_api->get_retry_period(rf_mac_setup->fhss_api, rf_mac_setup->active_pd_data_request->DstAddr, rf_mac_setup->dev_driver->phy_driver->phy_MTU);
|
||||
}
|
||||
}
|
||||
return backoff_in_us;
|
||||
}
|
||||
|
@ -199,6 +210,20 @@ int8_t mac_pd_sap_req(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Abort active PHY transmission.
|
||||
*
|
||||
* \param rf_mac_setup pointer to MAC.
|
||||
*
|
||||
*/
|
||||
void mac_pd_abort_active_tx(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
||||
{
|
||||
phy_csma_params_t csma_params;
|
||||
// Set TX time to 0 to abort current transmission
|
||||
csma_params.backoff_time = 0;
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t *) &csma_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PHY TX time.
|
||||
*
|
||||
|
@ -227,6 +252,9 @@ void mac_pd_sap_set_phy_tx_time(protocol_interface_rf_mac_setup_s *rf_mac_setup,
|
|||
*/
|
||||
static uint32_t mac_pd_sap_get_phy_rx_time(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
||||
{
|
||||
if (!rf_mac_setup->rf_csma_extension_supported) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t rx_time_buffer[4];
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_READ_RX_TIME, rx_time_buffer);
|
||||
return common_read_32_bit(rx_time_buffer);
|
||||
|
@ -341,6 +369,10 @@ static void mac_sap_no_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
|
|||
rf_ptr->mac_cca_retry = 0;
|
||||
rf_ptr->mac_tx_retry++; //Update retry counter
|
||||
mac_csma_param_init(rf_ptr);
|
||||
// Increase current backoff exponent when retry count grows
|
||||
for (int retry_index = rf_ptr->mac_tx_retry; retry_index > 0; retry_index--) {
|
||||
mac_csma_BE_update(rf_ptr);
|
||||
}
|
||||
rf_ptr->mac_tx_status.retry++;
|
||||
/*Send retry using random interval*/
|
||||
if (mcps_pd_data_rebuild(rf_ptr, rf_ptr->active_pd_data_request)) {
|
||||
|
@ -387,17 +419,17 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
if (status == PHY_LINK_CCA_PREPARE) {
|
||||
|
||||
if (rf_ptr->mac_ack_tx_active) {
|
||||
return 0;
|
||||
return PHY_TX_ALLOWED;
|
||||
}
|
||||
|
||||
if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) {
|
||||
return 0;
|
||||
return PHY_TX_ALLOWED;
|
||||
}
|
||||
|
||||
if (rf_ptr->fhss_api) {
|
||||
mac_pre_build_frame_t *active_buf = rf_ptr->active_pd_data_request;
|
||||
if (!active_buf) {
|
||||
return -1;
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
// Change to destination channel and write synchronization info to Beacon frames here
|
||||
|
@ -408,16 +440,22 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
// When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer
|
||||
if (tx_handle_retval == -1) {
|
||||
mac_sap_cca_fail_cb(rf_ptr);
|
||||
return -2;
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
}
|
||||
// When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back
|
||||
// to queue by using CCA fail event
|
||||
if (tx_handle_retval == -3) {
|
||||
mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
|
||||
return -3;
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
} else if (tx_handle_retval == -2) {
|
||||
mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION);
|
||||
return -2;
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
}
|
||||
if (active_buf->csma_periods_left > 0) {
|
||||
active_buf->csma_periods_left--;
|
||||
active_buf->tx_time += rf_ptr->multi_cca_interval;
|
||||
mac_pd_sap_set_phy_tx_time(rf_ptr, active_buf->tx_time, true);
|
||||
return PHY_RESTART_CSMA;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,6 +517,9 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
mac_sap_cca_fail_cb(rf_ptr);
|
||||
break;
|
||||
|
||||
case PHY_LINK_CCA_OK:
|
||||
break;
|
||||
|
||||
case PHY_LINK_TX_FAIL:
|
||||
mac_sap_no_ack_cb(rf_ptr);
|
||||
break;
|
||||
|
@ -531,7 +572,7 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool mac_pd_sap_ack_validation(protocol_interface_rf_mac_setup_s *rf_ptr, mac_fcf_sequence_t *fcf_dsn, const uint8_t *data_ptr)
|
||||
static bool mac_pd_sap_ack_validation(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_dsn, const uint8_t *data_ptr)
|
||||
{
|
||||
if (!rf_ptr->active_pd_data_request || !rf_ptr->active_pd_data_request->fcf_dsn.ackRequested) {
|
||||
return false; //No active Data request anymore or no ACK request for current TX
|
||||
|
@ -587,77 +628,133 @@ static bool mac_pd_sap_ack_validation(protocol_interface_rf_mac_setup_s *rf_ptr,
|
|||
return true;
|
||||
}
|
||||
|
||||
int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
||||
static int8_t mac_pd_sap_validate_fcf(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
|
||||
{
|
||||
protocol_interface_rf_mac_setup_s *rf_ptr = (protocol_interface_rf_mac_setup_s *)identifier;
|
||||
mac_pre_parsed_frame_t *buffer = NULL;
|
||||
|
||||
if (!rf_ptr || !message) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!rf_ptr->macUpState) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (message->id == MAC15_4_PD_SAP_DATA_IND) {
|
||||
const uint8_t *ptr;
|
||||
arm_pd_sap_generic_ind_t *pd_data_ind = &(message->message.generic_data_ind);
|
||||
|
||||
if (pd_data_ind->data_len < 3) {
|
||||
return -1;
|
||||
}
|
||||
ptr = pd_data_ind->data_ptr;
|
||||
|
||||
uint32_t time_stamp = 0;
|
||||
if (rf_ptr->rf_csma_extension_supported) {
|
||||
time_stamp = mac_pd_sap_get_phy_rx_time(rf_ptr);
|
||||
}
|
||||
mac_fcf_sequence_t fcf_read;
|
||||
ptr = mac_header_parse_fcf_dsn(&fcf_read, ptr);
|
||||
//Check PanID presents at header
|
||||
fcf_read.DstPanPresents = mac_dst_panid_present(&fcf_read);
|
||||
fcf_read.SrcPanPresents = mac_src_panid_present(&fcf_read);
|
||||
int16_t length = pd_data_ind->data_len;
|
||||
if (!rf_ptr->macProminousMode) {
|
||||
|
||||
//Unsupported Frame
|
||||
if (fcf_read.frametype > FC_CMD_FRAME || (fcf_read.frametype == FC_ACK_FRAME && fcf_read.frameVersion != MAC_FRAME_VERSION_2015)) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
|
||||
switch (fcf_read.frametype) {
|
||||
switch (fcf_read->frametype) {
|
||||
case FC_DATA_FRAME:
|
||||
if (fcf_read.SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
||||
if (fcf_read->SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
||||
return -1;
|
||||
} else if (fcf_read.DstAddrMode == MAC_ADDR_MODE_NONE && fcf_read.frameVersion != MAC_FRAME_VERSION_2015) {
|
||||
} else if (fcf_read->DstAddrMode == MAC_ADDR_MODE_NONE && fcf_read->frameVersion != MAC_FRAME_VERSION_2015) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case FC_BEACON_FRAME:
|
||||
if (fcf_read.SrcAddrMode == MAC_ADDR_MODE_NONE || fcf_read.DstAddrMode != MAC_ADDR_MODE_NONE) {
|
||||
if (fcf_read->SrcAddrMode == MAC_ADDR_MODE_NONE || fcf_read->DstAddrMode != MAC_ADDR_MODE_NONE) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case FC_ACK_FRAME:
|
||||
//Validate here that we are waiting ack
|
||||
if (fcf_read.ackRequested) {
|
||||
// Only accept version 2015 Acks
|
||||
if (fcf_read->frameVersion != MAC_FRAME_VERSION_2015) {
|
||||
return -1;
|
||||
}
|
||||
//Validate Ack doesn't request Ack
|
||||
if (fcf_read->ackRequested) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Validate ACK
|
||||
if (!mac_pd_sap_ack_validation(rf_ptr, &fcf_read, pd_data_ind->data_ptr)) {
|
||||
if (!mac_pd_sap_ack_validation(rf_ptr, fcf_read, pd_data_ind->data_ptr)) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case FC_CMD_FRAME:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool mac_pd_sap_panid_filter_common(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint16_t own_pan_id)
|
||||
{
|
||||
// Beacon frames shouldn't be dropped as they might be used by load balancing
|
||||
if (fcf_read->frametype == MAC_FRAME_BEACON) {
|
||||
return true;
|
||||
}
|
||||
if (own_pan_id == 0xffff) {
|
||||
return true;
|
||||
}
|
||||
uint16_t dst_pan_id = mac_header_get_dst_panid(fcf_read, mac_header, 0xffff);
|
||||
if (dst_pan_id == 0xffff) {
|
||||
return true;
|
||||
}
|
||||
if (own_pan_id == dst_pan_id) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mac_pd_sap_panid_v2_filter(const uint8_t *ptr, const mac_fcf_sequence_t *fcf_read, uint16_t pan_id)
|
||||
{
|
||||
if ((fcf_read->DstAddrMode == MAC_ADDR_MODE_NONE) && (fcf_read->frametype == FC_DATA_FRAME || fcf_read->frametype == FC_CMD_FRAME)) {
|
||||
return true;
|
||||
}
|
||||
if ((fcf_read->DstAddrMode == MAC_ADDR_MODE_64_BIT) && (fcf_read->SrcAddrMode == MAC_ADDR_MODE_64_BIT) && fcf_read->intraPan) {
|
||||
return true;
|
||||
}
|
||||
return mac_pd_sap_panid_filter_common(ptr, fcf_read, pan_id);
|
||||
}
|
||||
|
||||
static bool mac_pd_sap_addr_filter_common(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint8_t *mac_64bit_addr, uint16_t mac_16bit_addr)
|
||||
{
|
||||
uint8_t cmp_table[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
uint8_t dst_addr[8];
|
||||
mac_header_get_dst_address(fcf_read, mac_header, dst_addr);
|
||||
|
||||
switch (fcf_read->DstAddrMode) {
|
||||
case MAC_ADDR_MODE_16_BIT:
|
||||
if (!memcmp(dst_addr, cmp_table, 2)) {
|
||||
return true;
|
||||
}
|
||||
uint8_t temp[2];
|
||||
common_write_16_bit(mac_16bit_addr, temp);
|
||||
if (!memcmp(temp, dst_addr, 2)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MAC_ADDR_MODE_64_BIT:
|
||||
if (!memcmp(dst_addr, cmp_table, 8)) {
|
||||
return true;
|
||||
}
|
||||
if (!memcmp(mac_64bit_addr, dst_addr, 8)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MAC_ADDR_MODE_NONE:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Generate ACK when Extension is enabled and ACK is requested
|
||||
if (rf_ptr->mac_extension_enabled && fcf_read.ackRequested && fcf_read.frameVersion == MAC_FRAME_VERSION_2015) {
|
||||
//SEND ACK here
|
||||
static bool mac_pd_sap_addr_v2_filter(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint8_t *mac_64bit_addr, uint16_t mac_16bit_addr)
|
||||
{
|
||||
return mac_pd_sap_addr_filter_common(mac_header, fcf_read, mac_64bit_addr, mac_16bit_addr);
|
||||
}
|
||||
|
||||
static bool mac_pd_sap_rx_filter(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint8_t phy_filter_mask, uint8_t *mac_64bit_addr, uint16_t mac_16bit_addr, uint16_t pan_id)
|
||||
{
|
||||
uint8_t version = fcf_read->frameVersion;
|
||||
|
||||
if (version == MAC_FRAME_VERSION_2015 && !(phy_filter_mask & (1 << MAC_FRAME_VERSION_2))) {
|
||||
if (!mac_pd_sap_panid_v2_filter(mac_header, fcf_read, pan_id)) {
|
||||
return false;
|
||||
}
|
||||
if (!mac_pd_sap_addr_v2_filter(mac_header, fcf_read, mac_64bit_addr, mac_16bit_addr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
|
||||
{
|
||||
//Generate ACK when Extension is enabled and ACK is requested only for version 2 frames.
|
||||
if (!rf_ptr->mac_extension_enabled || !fcf_read->ackRequested || (fcf_read->frameVersion != MAC_FRAME_VERSION_2015)) {
|
||||
return 0;
|
||||
}
|
||||
if (rf_ptr->mac_ack_tx_active) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -667,48 +764,38 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
|||
mac_api->enhanced_ack_data_req_cb(mac_api, &ack_payload, pd_data_ind->dbm, pd_data_ind->link_quality);
|
||||
//Calculate Delta time
|
||||
|
||||
if (mcps_generic_ack_build(rf_ptr, &fcf_read, pd_data_ind->data_ptr, &ack_payload, time_stamp) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
|
||||
return mcps_generic_ack_build(rf_ptr, fcf_read, pd_data_ind->data_ptr, &ack_payload);
|
||||
}
|
||||
|
||||
static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
|
||||
{
|
||||
mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
|
||||
if (!buffer) {
|
||||
sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0);
|
||||
return -3;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Copy Pre Parsed values
|
||||
buffer->fcf_dsn = fcf_read;
|
||||
buffer->timestamp = time_stamp;
|
||||
|
||||
buffer->fcf_dsn = *fcf_read;
|
||||
buffer->timestamp = mac_pd_sap_get_phy_rx_time(rf_ptr);
|
||||
buffer->ack_pendinfg_status = mac_data_interface_read_last_ack_pending_status(rf_ptr);
|
||||
|
||||
|
||||
// Upward direction functions assume no headroom and are trusting that removed bytes are still valid.
|
||||
// see mac.c:655
|
||||
|
||||
/* Set default flags */
|
||||
buffer->dbm = pd_data_ind->dbm;
|
||||
buffer->LQI = pd_data_ind->link_quality;
|
||||
buffer->mac_class_ptr = rf_ptr;
|
||||
//Dnamic calculation for FCF + SEQ parse
|
||||
buffer->mac_header_length = ptr - pd_data_ind->data_ptr;
|
||||
|
||||
if (!rf_ptr->macProminousMode) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int8_t mac_pd_sap_parse_length_fields(mac_pre_parsed_frame_t *buffer, arm_pd_sap_generic_ind_t *pd_data_ind, const uint8_t *parse_ptr)
|
||||
{
|
||||
if (buffer->fcf_dsn.frametype > FC_CMD_FRAME) {
|
||||
goto ERROR_HANDLER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer->mac_header_length = parse_ptr - pd_data_ind->data_ptr;
|
||||
int16_t length = pd_data_ind->data_len;
|
||||
buffer->mac_header_length += mac_header_address_length(&buffer->fcf_dsn);
|
||||
|
||||
length -= buffer->mac_header_length;
|
||||
|
||||
if (length < 0) {
|
||||
goto ERROR_HANDLER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer->mac_payload_length = (buffer->frameLength - buffer->mac_header_length);
|
||||
|
@ -747,38 +834,80 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
|||
|
||||
//Verify that data length is not negative
|
||||
if (length < 0) {
|
||||
goto ERROR_HANDLER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer->mac_payload_length -= (buffer->security_aux_header_length + mic_len);
|
||||
}
|
||||
|
||||
//Do not accept command frame with length 0
|
||||
if (fcf_read.frametype == FC_CMD_FRAME && length == 0) {
|
||||
goto ERROR_HANDLER;
|
||||
if (buffer->fcf_dsn.frametype == FC_CMD_FRAME && length == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
||||
{
|
||||
protocol_interface_rf_mac_setup_s *rf_ptr = (protocol_interface_rf_mac_setup_s *)identifier;
|
||||
|
||||
if (!rf_ptr || !message) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Parse IE Elements
|
||||
if (!rf_ptr->macUpState) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (message->id == MAC15_4_PD_SAP_DATA_IND) {
|
||||
arm_pd_sap_generic_ind_t *pd_data_ind = &(message->message.generic_data_ind);
|
||||
if (pd_data_ind->data_len < 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mac_fcf_sequence_t fcf_read;
|
||||
const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr);
|
||||
|
||||
mac_pre_parsed_frame_t *buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind);
|
||||
if (buffer && mac_filter_modify_link_quality(rf_ptr->mac_interface_id, buffer) == 1) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
if (!rf_ptr->macProminousMode) {
|
||||
if (mac_pd_sap_validate_fcf(rf_ptr, &fcf_read, pd_data_ind)) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
if (!mac_pd_sap_rx_filter(pd_data_ind->data_ptr, &fcf_read, rf_ptr->mac_frame_filters, rf_ptr->mac64, rf_ptr->mac_short_address, rf_ptr->pan_id)) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
if (mac_pd_sap_generate_ack(rf_ptr, &fcf_read, pd_data_ind)) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
if (buffer) {
|
||||
if (mac_pd_sap_parse_length_fields(buffer, pd_data_ind, ptr)) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
if (!mac_header_information_elements_parse(buffer)) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rf_ptr->macProminousMode && buffer->fcf_dsn.frametype == FC_ACK_FRAME) {
|
||||
if (buffer->fcf_dsn.frametype == FC_ACK_FRAME) {
|
||||
if (mac_data_interface_tx_done_by_ack_cb(rf_ptr, buffer)) {
|
||||
mcps_sap_pre_parsed_frame_buffer_free(buffer);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!buffer) {
|
||||
sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0);
|
||||
return -3;
|
||||
}
|
||||
if (mcps_sap_pd_ind(buffer) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ERROR_HANDLER:
|
||||
mcps_sap_pre_parsed_frame_buffer_free(buffer);
|
||||
sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0);
|
||||
return -1;
|
||||
|
||||
|
||||
} else if (message->id == MAC15_4_PD_SAP_DATA_TX_CONFIRM) {
|
||||
arm_pd_sap_15_4_confirm_with_params_t *pd_data_cnf = &(message->message.mac15_4_pd_sap_confirm);
|
||||
return mac_data_interface_tx_done_cb(rf_ptr, pd_data_cnf->status, pd_data_cnf->cca_retry, pd_data_cnf->tx_retry);
|
||||
|
|
|
@ -39,6 +39,8 @@ int8_t mac_pd_sap_req(struct protocol_interface_rf_mac_setup *rf_mac_setup);
|
|||
|
||||
int8_t mac_plme_cca_req(struct protocol_interface_rf_mac_setup *rf_mac_setup);
|
||||
|
||||
void mac_pd_abort_active_tx(struct protocol_interface_rf_mac_setup *rf_mac_setup);
|
||||
|
||||
void mac_pd_sap_set_phy_tx_time(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint32_t tx_time, bool cca_enabled);
|
||||
|
||||
void mac_pd_sap_rf_low_level_function_set(void *mac_ptr, void *driver);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Service_Libs/Trickle/trickle.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
#include "MPL/mpl.h"
|
||||
|
||||
#define TRACE_GROUP "mpl"
|
||||
|
@ -1105,7 +1106,8 @@ static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, i
|
|||
|
||||
/* "Compress" seed ID if it's the IPv6 source address */
|
||||
/* (For Thread, also compress if source is the 16-bit address) */
|
||||
if (seed_id_len == 16 && addr_ipv6_equal(seed_id, buf->src_sa.address)) {
|
||||
/* (For Wi-sun, not support seed id address compression */
|
||||
if (!ws_info(buf->interface) && seed_id_len == 16 && addr_ipv6_equal(seed_id, buf->src_sa.address)) {
|
||||
seed_id_len = 0;
|
||||
} else if (seed_id_len == 2 && thread_addr_is_mesh_local_16(buf->src_sa.address, buf->interface) &&
|
||||
seed_id[0] == buf->src_sa.address[14] && seed_id[1] == buf->src_sa.address[15]) {
|
||||
|
|
|
@ -121,6 +121,7 @@ typedef enum icmp_state {
|
|||
ER_BOOTSTRAP_SCAN_FAIL,
|
||||
ER_BOOTSTRAP_LEADER_UP,
|
||||
ER_BOOTSTRAP_NEW_FRAGMENT_START,
|
||||
ER_WAIT_RESTART,
|
||||
ER_RPL_LOCAL_REPAIR,
|
||||
} icmp_state_t;
|
||||
|
||||
|
@ -514,4 +515,5 @@ extern void protocol_core_dhcpv6_allocated_address_remove(protocol_interface_inf
|
|||
extern void nwk_bootsrap_state_update(arm_nwk_interface_status_type_e posted_event, protocol_interface_info_entry_t *cur);
|
||||
void bootsrap_next_state_kick(icmp_state_t new_state, protocol_interface_info_entry_t *cur);
|
||||
int8_t protocol_interface_address_compare(const uint8_t *addr);
|
||||
bool protocol_interface_any_address_match(const uint8_t *prefix, uint8_t prefix_len);
|
||||
#endif /* _NS_PROTOCOL_H */
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
|
||||
#include "Service_Libs/load_balance/load_balance_api.h"
|
||||
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
|
||||
#include "Service_Libs/etx/etx.h"
|
||||
|
||||
#include "mac_api.h"
|
||||
#include "ethernet_mac_api.h"
|
||||
|
@ -260,6 +261,7 @@ void core_timer_event_handle(uint16_t ticksUpdate)
|
|||
if (cur->nwk_wpan_nvm_api) {
|
||||
cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, false);
|
||||
}
|
||||
etx_cache_timer(cur->id, seconds);
|
||||
}
|
||||
} else if (cur->nwk_id == IF_IPV6) {
|
||||
//Slow Pointer Update
|
||||
|
@ -300,6 +302,9 @@ void core_timer_event_handle(uint16_t ticksUpdate)
|
|||
ipv6_destination_cache_timer(seconds);
|
||||
ipv6_frag_timer(seconds);
|
||||
cipv6_frag_timer(seconds);
|
||||
#ifdef HAVE_WS
|
||||
ws_pae_controller_slow_timer(seconds);
|
||||
#endif
|
||||
protocol_6lowpan_mle_timer(seconds);
|
||||
/* This limit bad behaviour device's MLE link reject generation */
|
||||
|
||||
|
@ -339,7 +344,7 @@ void core_timer_event_handle(uint16_t ticksUpdate)
|
|||
icmpv6_radv_timer(ticksUpdate);
|
||||
protocol_core_security_tick_update(ticksUpdate);
|
||||
#ifdef HAVE_WS
|
||||
ws_pae_controller_timer(ticksUpdate);
|
||||
ws_pae_controller_fast_timer(ticksUpdate);
|
||||
#endif
|
||||
platform_enter_critical();
|
||||
protocol_core_timer_info.core_timer_event = false;
|
||||
|
@ -1135,3 +1140,27 @@ int8_t protocol_interface_address_compare(const uint8_t *addr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static bool protocol_address_prefix_cmp(protocol_interface_info_entry_t *interface, const uint8_t *prefix, uint8_t prefix_len)
|
||||
{
|
||||
ns_list_foreach(if_address_entry_t, adr, &interface->ip_addresses) {
|
||||
if (bitsequal(adr->address, prefix, prefix_len)) {
|
||||
/* Prefix stil used at list so stop checking */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool protocol_interface_any_address_match(const uint8_t *prefix, uint8_t prefix_len)
|
||||
{
|
||||
ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
|
||||
|
||||
if (protocol_address_prefix_cmp(cur, prefix, prefix_len)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -151,17 +151,6 @@ static void rpl_control_publish_own_addresses(rpl_domain_t *domain, rpl_instance
|
|||
}
|
||||
}
|
||||
|
||||
static void rpl_control_publish_own_address(rpl_domain_t *domain, const if_address_entry_t *addr)
|
||||
{
|
||||
ns_list_foreach(rpl_instance_t, instance, &domain->instances) {
|
||||
if (!rpl_instance_am_root(instance)) {
|
||||
uint32_t descriptor = 0;
|
||||
bool want_descriptor = rpl_policy_target_descriptor_for_own_address(domain, addr->address, addr->source, addr->data, &descriptor);
|
||||
rpl_instance_publish_dao_target(instance, addr->address, 128, addr->valid_lifetime, true, want_descriptor, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime)
|
||||
{
|
||||
ns_list_foreach(rpl_instance_t, instance, &domain->instances) {
|
||||
|
@ -260,10 +249,6 @@ static void rpl_control_addr_notifier(struct protocol_interface_info_entry *inte
|
|||
}
|
||||
|
||||
switch (reason) {
|
||||
case ADDR_CALLBACK_DAD_COMPLETE:
|
||||
case ADDR_CALLBACK_REFRESHED:
|
||||
rpl_control_publish_own_address(interface->rpl_domain, addr);
|
||||
break;
|
||||
case ADDR_CALLBACK_DELETED:
|
||||
rpl_control_unpublish_address(interface->rpl_domain, addr->address);
|
||||
break;
|
||||
|
@ -345,11 +330,7 @@ void rpl_control_set_domain_on_interface(protocol_interface_info_entry_t *cur, r
|
|||
cur->rpl_domain = domain;
|
||||
addr_add_group(cur, ADDR_LINK_LOCAL_ALL_RPL_NODES);
|
||||
}
|
||||
ns_list_foreach(if_address_entry_t, addr, &cur->ip_addresses) {
|
||||
if (!addr_is_ipv6_link_local(addr->address)) {
|
||||
rpl_control_publish_own_address(domain, addr);
|
||||
}
|
||||
}
|
||||
|
||||
if (downstream) {
|
||||
domain->non_storing_downstream_interface = cur->id;
|
||||
}
|
||||
|
@ -690,8 +671,9 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
|
|||
bool router_addr_set = false;
|
||||
|
||||
rpl_neighbour_t *pref_parent = rpl_instance_preferred_parent(instance);
|
||||
|
||||
// const rpl_dodag_conf_t *conf = rpl_dodag_get_config(dodag);
|
||||
if (neighbour == pref_parent) {
|
||||
rpl_dodag_update_unpublished_dio_prefix_start(dodag);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
const uint8_t *ptr = rpl_control_find_option(start, end - start, RPL_PREFIX_INFO_OPTION, 30);
|
||||
|
@ -735,6 +717,9 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
|
|||
|
||||
start = ptr + 32;
|
||||
}
|
||||
if (neighbour == pref_parent) {
|
||||
rpl_dodag_update_unpublished_dio_prefix_finish(dodag);
|
||||
}
|
||||
}
|
||||
|
||||
void rpl_control_process_prefix_option(prefix_entry_t *prefix, protocol_interface_info_entry_t *cur)
|
||||
|
@ -894,10 +879,6 @@ malformed:
|
|||
if (!instance) {
|
||||
return buffer_free(buf);
|
||||
}
|
||||
|
||||
if ((g_mop_prf & RPL_MODE_MASK) != RPL_MODE_NO_DOWNWARD) {
|
||||
rpl_control_publish_own_addresses(domain, instance);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lookup any existing neighbour entry */
|
||||
|
@ -1156,7 +1137,7 @@ void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entr
|
|||
} else {
|
||||
prefix->options &= ~ PIO_R;
|
||||
|
||||
if (rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING) {
|
||||
if (rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING && prefix->lifetime != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1194,7 +1175,7 @@ void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entr
|
|||
ns_list_foreach_safe(prefix_entry_t, prefix, prefixes) {
|
||||
/* See equivalent checks in length calculation above */
|
||||
if ((prefix->options & (PIO_L | RPL_PIO_PUBLISHED)) == PIO_L ||
|
||||
(!(prefix->options & PIO_R) && rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING)) {
|
||||
(!(prefix->options & PIO_R) && rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING && prefix->lifetime != 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1207,6 +1188,14 @@ void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entr
|
|||
common_write_32_bit(0, ptr + 12); // reserved
|
||||
memcpy(ptr + 16, prefix->prefix, 16);
|
||||
ptr += 32;
|
||||
/* Transmitting a multicast DIO decrements the hold count for 0 lifetime prefixes */
|
||||
if (dst == NULL && (prefix->options & RPL_PIO_AGE)) {
|
||||
int hold_count = prefix->options & RPL_PIO_HOLD_MASK;
|
||||
if (hold_count) {
|
||||
hold_count--;
|
||||
prefix->options = (prefix->options & ~RPL_PIO_HOLD_MASK) | hold_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ns_list_foreach_safe(rpl_dio_route_t, route, routes) {
|
||||
|
@ -1616,6 +1605,7 @@ void rpl_control_slow_timer(uint16_t seconds)
|
|||
|
||||
ns_list_foreach(rpl_domain_t, domain, &rpl_domains) {
|
||||
ns_list_foreach_safe(rpl_instance_t, instance, &domain->instances) {
|
||||
rpl_control_publish_own_addresses(domain, instance);
|
||||
rpl_instance_slow_timer(instance, seconds);
|
||||
rpl_downward_dao_slow_timer(instance, seconds);
|
||||
/* We purge one item from each instance, so as not to favour one domain or instance */
|
||||
|
@ -1654,13 +1644,14 @@ rpl_instance_t *rpl_control_lookup_instance(rpl_domain_t *domain, uint8_t instan
|
|||
return rpl_lookup_instance(domain, instance_id, dodagid);
|
||||
}
|
||||
|
||||
bool rpl_control_get_instance_dao_target_count(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid, uint16_t *target_count)
|
||||
bool rpl_control_get_instance_dao_target_count(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid, const uint8_t *prefix, uint16_t *target_count)
|
||||
{
|
||||
rpl_instance_t *instance = rpl_lookup_instance(domain, instance_id, dodagid);
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
*target_count = rpl_upward_read_dao_target_list_size(instance);
|
||||
|
||||
*target_count = rpl_upward_read_dao_target_list_size(instance, prefix);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void rpl_control_print(route_print_fn_t *print_fn);
|
|||
|
||||
struct rpl_instance *rpl_control_enumerate_instances(rpl_domain_t *domain, struct rpl_instance *instance);
|
||||
struct rpl_instance *rpl_control_lookup_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid);
|
||||
bool rpl_control_get_instance_dao_target_count(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid, uint16_t *target_count);
|
||||
bool rpl_control_get_instance_dao_target_count(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid, const uint8_t *prefix, uint16_t *target_count);
|
||||
bool rpl_control_read_dodag_info(const struct rpl_instance *instance, struct rpl_dodag_info_t *dodag_info);
|
||||
const rpl_dodag_conf_t *rpl_control_get_dodag_config(const struct rpl_instance *instance);
|
||||
const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global);
|
||||
|
|
|
@ -345,8 +345,9 @@ void rpl_instance_publish_dao_target(rpl_instance_t *instance, const uint8_t *pr
|
|||
{
|
||||
rpl_dao_target_t *target = rpl_instance_lookup_published_dao_target(instance, prefix, prefix_len);
|
||||
if (target) {
|
||||
int diff = target->lifetime > valid_lifetime ? target->lifetime - valid_lifetime : valid_lifetime - target->lifetime;
|
||||
target->lifetime = valid_lifetime;
|
||||
if (!own) {
|
||||
if (!own && diff > 60) {
|
||||
/* For non-owned targets, publish triggers a refresh */
|
||||
rpl_downward_target_refresh(target);
|
||||
rpl_instance_dao_trigger(instance, 0);
|
||||
|
@ -590,7 +591,7 @@ void rpl_instance_send_address_registration(protocol_interface_info_entry_t *int
|
|||
|
||||
aro.status = ARO_SUCCESS;
|
||||
aro.present = true;
|
||||
aro.lifetime = addr->valid_lifetime;
|
||||
aro.lifetime = (addr->valid_lifetime / 60) + 1;
|
||||
memcpy(aro.eui64, interface->mac, 8);
|
||||
|
||||
// go through neighbour list, and send to all assigned parents.
|
||||
|
|
|
@ -932,6 +932,33 @@ const prefix_list_t *rpl_dodag_get_prefix_list(const rpl_dodag_t *dodag)
|
|||
{
|
||||
return &dodag->prefixes;
|
||||
}
|
||||
|
||||
/* Called before updating all prefixes in a DIO */
|
||||
void rpl_dodag_update_unpublished_dio_prefix_start(rpl_dodag_t *dodag)
|
||||
{
|
||||
/* Clear age flags - will use as a marker for entries being in the DIO */
|
||||
ns_list_foreach(prefix_entry_t, entry, &dodag->prefixes) {
|
||||
if (!(entry->options & RPL_PIO_PUBLISHED)) {
|
||||
entry->options &= ~RPL_PIO_AGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called after updating all prefixes in a DIO */
|
||||
void rpl_dodag_update_unpublished_dio_prefix_finish(rpl_dodag_t *dodag)
|
||||
{
|
||||
/* Any remaining non-published entries that don't have the age flag
|
||||
* set are not being sent by parent any more, so we should stop sending
|
||||
* too, except for the minimimum count requirement on 0 lifetime.
|
||||
*/
|
||||
ns_list_foreach_safe(prefix_entry_t, entry, &dodag->prefixes) {
|
||||
if ((entry->options & (RPL_PIO_PUBLISHED | RPL_PIO_AGE | RPL_PIO_HOLD_MASK)) == 0) {
|
||||
rpl_dodag_delete_dio_prefix(dodag, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prefix_entry_t *rpl_dodag_update_dio_prefix(rpl_dodag_t *dodag, const uint8_t *prefix, uint8_t prefix_len, uint8_t flags, uint32_t lifetime, uint32_t preftime, bool publish, bool age)
|
||||
{
|
||||
/* Don't let them set funny flags - we won't propagate them either.
|
||||
|
@ -948,20 +975,30 @@ prefix_entry_t *rpl_dodag_update_dio_prefix(rpl_dodag_t *dodag, const uint8_t *p
|
|||
flags |= RPL_PIO_AGE;
|
||||
}
|
||||
|
||||
if (lifetime == 0) {
|
||||
flags |= RPL_MAX_FINAL_RTR_ADVERTISEMENTS;
|
||||
}
|
||||
|
||||
prefix_entry_t *entry = icmpv6_prefix_add(&dodag->prefixes, prefix, prefix_len, lifetime, preftime, flags);
|
||||
prefix_entry_t *entry = icmpv6_prefix_add(&dodag->prefixes, prefix, prefix_len, lifetime, preftime, 0xff);
|
||||
/* icmpv6_prefix_add indicates a new entry by leaving options set to 0xFF */
|
||||
if (entry) {
|
||||
/* Newly-seen zero lifetimes should be advertised at least a few times -
|
||||
* count this down in the RPL_PIO_HOLD_COUNT field
|
||||
*/
|
||||
if (lifetime == 0 && (entry->options == 0xFF || entry->lifetime != 0)) {
|
||||
flags |= RPL_MAX_FINAL_RTR_ADVERTISEMENTS;
|
||||
}
|
||||
entry->options = flags;
|
||||
entry->lifetime = lifetime;
|
||||
entry->preftime = preftime;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
void rpl_dodag_delete_dio_prefix(rpl_dodag_t *dodag, prefix_entry_t *prefix)
|
||||
{
|
||||
rpl_instance_t *instance = dodag->instance;
|
||||
|
||||
if (instance && instance->domain->prefix_cb) {
|
||||
instance->domain->prefix_cb(prefix, instance->domain->cb_handle, NULL);
|
||||
}
|
||||
|
||||
ns_list_remove(&dodag->prefixes, prefix);
|
||||
ns_dyn_mem_free(prefix);
|
||||
}
|
||||
|
@ -984,7 +1021,11 @@ static void rpl_dodag_age_prefixes(rpl_dodag_t *dodag, uint16_t seconds)
|
|||
prefix->lifetime -= seconds;
|
||||
} else {
|
||||
prefix->lifetime = 0;
|
||||
if ((prefix->options & RPL_PIO_HOLD_MASK) == 0) {
|
||||
/* Only delete on timeout if we're publishing - otherwise we will
|
||||
* keep advertising until we see our parent stop advertising it - deletion
|
||||
* is handled in rpl_control_process_prefix_options.
|
||||
*/
|
||||
if ((prefix->options & (RPL_PIO_PUBLISHED | RPL_PIO_HOLD_MASK)) == RPL_PIO_PUBLISHED) {
|
||||
rpl_dodag_delete_dio_prefix(dodag, prefix);
|
||||
}
|
||||
}
|
||||
|
@ -1742,8 +1783,19 @@ void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t rpl_upward_read_dao_target_list_size(const rpl_instance_t *instance)
|
||||
uint16_t rpl_upward_read_dao_target_list_size(const rpl_instance_t *instance, const uint8_t *target_prefix)
|
||||
{
|
||||
|
||||
if (target_prefix) {
|
||||
uint16_t registered_address_count = 0;
|
||||
ns_list_foreach(rpl_dao_target_t, target, &instance->dao_targets) {
|
||||
if (bitsequal(target->prefix, target_prefix, 64)) {
|
||||
registered_address_count++;
|
||||
}
|
||||
}
|
||||
return registered_address_count;
|
||||
}
|
||||
|
||||
return ns_list_count(&instance->dao_targets);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,8 @@ rpl_dio_route_t *rpl_dodag_update_dio_route(rpl_dodag_t *dodag, const uint8_t *p
|
|||
void rpl_dodag_delete_dio_route(rpl_dodag_t *dodag, rpl_dio_route_t *route);
|
||||
const rpl_dio_route_list_t *rpl_dodag_get_route_list(const rpl_dodag_t *dodag);
|
||||
|
||||
void rpl_dodag_update_unpublished_dio_prefix_start(rpl_dodag_t *dodag);
|
||||
void rpl_dodag_update_unpublished_dio_prefix_finish(rpl_dodag_t *dodag);
|
||||
prefix_entry_t *rpl_dodag_update_dio_prefix(rpl_dodag_t *dodag, const uint8_t *prefix, uint8_t prefix_len, uint8_t flags, uint32_t lifetime, uint32_t preftime, bool publish, bool age);
|
||||
void rpl_dodag_delete_dio_prefix(rpl_dodag_t *dodag, prefix_entry_t *prefix);
|
||||
const prefix_list_t *rpl_dodag_get_prefix_list(const rpl_dodag_t *dodag);
|
||||
|
@ -143,5 +145,5 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance);
|
|||
void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print_fn);
|
||||
|
||||
bool rpl_upward_read_dodag_info(const rpl_instance_t *instance, struct rpl_dodag_info_t *dodag_info);
|
||||
uint16_t rpl_upward_read_dao_target_list_size(const rpl_instance_t *instance);
|
||||
uint16_t rpl_upward_read_dao_target_list_size(const rpl_instance_t *instance, const uint8_t *target_prefix);
|
||||
#endif /* RPL_UPWARD_H_ */
|
||||
|
|
|
@ -1161,7 +1161,7 @@ buffer_t *tls_client_up(buffer_t *buf, sec_suite_t *tls_suite)
|
|||
if (tls_header_ptr) {
|
||||
if (tls_header_ptr->type == TLS_HANDSHAKE && (tls_heap != 0)) {
|
||||
tr_debug("Type:Handshake");
|
||||
if ((tls_suite->state == TLS_CHANGE_CHIPHER)) {
|
||||
if (tls_suite->state == TLS_CHANGE_CHIPHER) {
|
||||
if (tls_header_ptr->length < 32) {
|
||||
tr_debug("Too short Chiher Text");
|
||||
} else if ((algo_ok & 0x20) && (tls_suite->state == PRF_CALC)) {
|
||||
|
@ -1477,7 +1477,7 @@ buffer_t *tls_server_up(buffer_t *buf, sec_suite_t *tls_suite)
|
|||
if (tls_header_ptr) {
|
||||
if (tls_header_ptr->type == TLS_HANDSHAKE && (tls_heap != 0)) {
|
||||
tr_debug("Type:Handshake");
|
||||
if ((tls_suite->state == TLS_CHANGE_CHIPHER)) {
|
||||
if (tls_suite->state == TLS_CHANGE_CHIPHER) {
|
||||
if (tls_header_ptr->length < 32) {
|
||||
tr_debug("Too short Chiher Text");
|
||||
} else if ((algo_ok & 0x20) && (tls_suite->state == PRF_CALC)) {
|
||||
|
|
|
@ -274,5 +274,25 @@ uint16_t eapol_pdu_key_frame_init(eapol_pdu_t *eapol_pdu, uint16_t data_length,
|
|||
|
||||
}
|
||||
|
||||
uint8_t eapol_pdu_key_mask_get(eapol_pdu_t *eapol_pdu)
|
||||
{
|
||||
uint8_t key_mask = 0;
|
||||
|
||||
if (eapol_pdu->msg.key.key_information.install) {
|
||||
key_mask |= KEY_INFO_INSTALL;
|
||||
}
|
||||
if (eapol_pdu->msg.key.key_information.key_ack) {
|
||||
key_mask |= KEY_INFO_KEY_ACK;
|
||||
}
|
||||
if (eapol_pdu->msg.key.key_information.key_mic) {
|
||||
key_mask |= KEY_INFO_KEY_MIC;
|
||||
}
|
||||
if (eapol_pdu->msg.key.key_information.secured_key_frame) {
|
||||
key_mask |= KEY_INFO_SECURED_KEY_FRAME;
|
||||
}
|
||||
|
||||
return key_mask;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define EAPOL_KEY_TYPE 3
|
||||
#define EAPOL_KEY_NONCE_LEN 32
|
||||
#define EAPOL_KEY_MIC_LEN 16
|
||||
#define EAPOL_KEY_LEN 16
|
||||
|
||||
#define EAPOL_BASE_LENGTH 4 //Protocol version 1 byte, Packet type 1 byte, packet length 2 byte
|
||||
|
||||
|
@ -96,4 +97,18 @@ uint16_t eapol_pdu_key_frame_init(eapol_pdu_t *eapol_pdu, uint16_t data_length,
|
|||
|
||||
void eapol_write_key_packet_mic(uint8_t *eapol_pdu, uint8_t *mic);
|
||||
|
||||
#define KEY_INFO_INSTALL 0x01
|
||||
#define KEY_INFO_KEY_ACK 0x02
|
||||
#define KEY_INFO_KEY_MIC 0x04
|
||||
#define KEY_INFO_SECURED_KEY_FRAME 0x08
|
||||
|
||||
/**
|
||||
* eapol_pdu_key_mask_get gets masked EAPOL-Key message bits
|
||||
*
|
||||
* \param eapol_pdu EAPOL PDU
|
||||
*
|
||||
* \return mask
|
||||
*/
|
||||
uint8_t eapol_pdu_key_mask_get(eapol_pdu_t *eapol_pdu);
|
||||
|
||||
#endif /* EAPOL_HELPER_H_ */
|
||||
|
|
|
@ -45,7 +45,8 @@ struct kmp_api_s {
|
|||
kmp_type_e type; /**< KMP type */
|
||||
kmp_addr_t *addr; /**< Supplicant EUI-64, Relay IP address, Relay port */
|
||||
kmp_service_t *service; /**< KMP service */
|
||||
bool timer_start_pending; /**< Timer is pending to start */
|
||||
bool timer_start_pending : 1; /**< Timer is pending to start */
|
||||
bool receive_disable : 1; /**< Receiving disabled, do not route messages anymore */
|
||||
sec_prot_t sec_prot; /**< Security protocol interface */
|
||||
};
|
||||
|
||||
|
@ -88,6 +89,7 @@ static void kmp_sec_prot_timer_stop(sec_prot_t *prot);
|
|||
static void kmp_sec_prot_state_machine_call(sec_prot_t *prot);
|
||||
static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64);
|
||||
static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type);
|
||||
static void kmp_sec_prot_receive_disable(sec_prot_t *prot);
|
||||
|
||||
#define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot));
|
||||
|
||||
|
@ -126,6 +128,7 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type)
|
|||
kmp->addr = 0;
|
||||
kmp->service = service;
|
||||
kmp->timer_start_pending = false;
|
||||
kmp->receive_disable = false;
|
||||
|
||||
memset(&kmp->sec_prot, 0, sec_size);
|
||||
|
||||
|
@ -140,6 +143,7 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type)
|
|||
kmp->sec_prot.state_machine_call = kmp_sec_prot_state_machine_call;
|
||||
kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get;
|
||||
kmp->sec_prot.type_get = kmp_sec_prot_by_type_get;
|
||||
kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable;
|
||||
|
||||
if (sec_prot->init(&kmp->sec_prot) < 0) {
|
||||
ns_dyn_mem_free(kmp);
|
||||
|
@ -279,6 +283,12 @@ static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type)
|
|||
return &kmp_by_type->sec_prot;
|
||||
}
|
||||
|
||||
static void kmp_sec_prot_receive_disable(sec_prot_t *prot)
|
||||
{
|
||||
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
||||
kmp->receive_disable = true;
|
||||
}
|
||||
|
||||
void kmp_api_delete(kmp_api_t *kmp)
|
||||
{
|
||||
if (kmp->sec_prot.delete) {
|
||||
|
@ -312,9 +322,9 @@ kmp_type_e kmp_api_type_from_id_get(uint8_t kmp_id)
|
|||
case IEEE_802_11_4WH:
|
||||
return IEEE_802_11_4WH;
|
||||
case IEEE_802_11_GKH:
|
||||
return IEEE_802_1X_MKA;
|
||||
return IEEE_802_11_GKH;
|
||||
default:
|
||||
return INVALID_KMP_TYPE;
|
||||
return KMP_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,6 +436,11 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, kmp_type_e type, const
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Security protocol has disables message receiving
|
||||
if (kmp->receive_disable) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
|
||||
typedef enum {
|
||||
INVALID_KMP_TYPE = 0,
|
||||
KMP_TYPE_NONE = 0,
|
||||
|
||||
IEEE_802_1X_MKA = 1,
|
||||
IEEE_802_11_4WH = 6,
|
||||
|
|
|
@ -151,7 +151,7 @@ int8_t kmp_eapol_pdu_if_receive(protocol_interface_info_entry_t *interface_ptr,
|
|||
void *data_pdu = &eapol_kmp_pdu->kmp_data;
|
||||
|
||||
kmp_type_e type = kmp_api_type_from_id_get(eapol_kmp_pdu->kmp_id);
|
||||
if (type == INVALID_KMP_TYPE) {
|
||||
if (type == KMP_TYPE_NONE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ static void kmp_socket_if_socket_cb(void *ptr)
|
|||
data_ptr += 8;
|
||||
|
||||
kmp_type_e type = kmp_api_type_from_id_get(*data_ptr++);
|
||||
if (type == INVALID_KMP_TYPE) {
|
||||
if (type == KMP_TYPE_NONE) {
|
||||
ns_dyn_mem_free(pdu);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ typedef struct {
|
|||
tls_data_t tls_send; /**< EAP-TLS send buffer */
|
||||
tls_data_t tls_recv; /**< EAP-TLS receive buffer */
|
||||
uint8_t eap_id_seq; /**< EAP sequence */
|
||||
uint8_t recv_eap_id_seq; /**< Last received EAP sequence */
|
||||
uint8_t eap_code; /**< Received EAP code */
|
||||
uint8_t eap_type; /**< Received EAP type */
|
||||
int8_t tls_result; /**< Result of TLS operation */
|
||||
|
@ -72,7 +73,7 @@ static const trickle_params_t eap_tls_trickle_params = {
|
|||
.Imin = 200, /* 20s; ticks are 100ms */
|
||||
.Imax = 450, /* 45s */
|
||||
.k = 0, /* infinity - no consistency checking */
|
||||
.TimerExpirations = 4
|
||||
.TimerExpirations = 2
|
||||
};
|
||||
|
||||
static uint16_t auth_eap_tls_sec_prot_size(void);
|
||||
|
@ -129,6 +130,7 @@ static int8_t auth_eap_tls_sec_prot_init(sec_prot_t *prot)
|
|||
|
||||
data->tls_prot = NULL;
|
||||
data->eap_id_seq = 0;
|
||||
data->recv_eap_id_seq = 0;
|
||||
data->eap_code = 0;
|
||||
data->eap_type = 0;
|
||||
eap_tls_sec_prot_lib_message_init(&data->tls_recv);
|
||||
|
@ -188,21 +190,32 @@ static int8_t auth_eap_tls_sec_prot_message_handle(sec_prot_t *prot)
|
|||
uint16_t length = data->recv_eapol_pdu.msg.eap.length;
|
||||
|
||||
bool new_seq_id = false;
|
||||
bool old_seq_id = false;
|
||||
|
||||
// Already received sequence ID is received again, ignore
|
||||
if (data->recv_eapol_pdu.msg.eap.id_seq < data->eap_id_seq) {
|
||||
old_seq_id = true;
|
||||
} else if (data->recv_eapol_pdu.msg.eap.id_seq == data->eap_id_seq) {
|
||||
// Confirmation that supplicant has received the message, proceed with protocol
|
||||
if (data->recv_eapol_pdu.msg.eap.id_seq == data->eap_id_seq) {
|
||||
data->recv_eap_id_seq = data->recv_eapol_pdu.msg.eap.id_seq;
|
||||
data->eap_id_seq++;
|
||||
new_seq_id = true;
|
||||
}
|
||||
|
||||
tr_debug("recv EAP %s type %s id %i flags %x len %i", eap_msg_trace[data->eap_code - 1],
|
||||
tr_info("EAP-TLS: recv %s type %s id %i flags %x len %i, eui-64 %s", eap_msg_trace[data->eap_code - 1],
|
||||
data->eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->recv_eapol_pdu.msg.eap.id_seq,
|
||||
length >= 6 ? data_ptr[0] : 0, length);
|
||||
length >= 6 ? data_ptr[0] : 0, length, trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
if (old_seq_id) {
|
||||
return EAP_TLS_MSG_DECODE_ERROR;
|
||||
}
|
||||
|
||||
if (data->eap_type == EAP_IDENTITY) {
|
||||
return EAP_TLS_MSG_IDENTITY;
|
||||
}
|
||||
|
||||
if (!data_ptr || length < 6) {
|
||||
tr_error("EAP-TLS: decode error");
|
||||
return EAP_TLS_MSG_DECODE_ERROR;
|
||||
}
|
||||
|
||||
|
@ -226,16 +239,23 @@ static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_c
|
|||
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, TLS_HEAD_LEN, 0);
|
||||
flags = EAP_TLS_START;
|
||||
}
|
||||
} else if (eap_code != EAP_SUCCESS && eap_code != EAP_FAILURE) {
|
||||
} else if (eap_code == EAP_SUCCESS || eap_code == EAP_FAILURE) {
|
||||
// Send Success and Failure with same identifier as received in EAP Response
|
||||
data->eap_id_seq = data->recv_eap_id_seq;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t eapol_pdu_size;
|
||||
uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, flags, data->eap_id_seq, prot->header_size, &data->tls_send, &eapol_pdu_size);
|
||||
uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, &flags, data->eap_id_seq, prot->header_size, &data->tls_send, &eapol_pdu_size);
|
||||
if (!eapol_decoded_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_info("EAP-TLS: send %s type %s id %i flags %x len %i, eui-64: %s", eap_msg_trace[eap_code - 1],
|
||||
eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->eap_id_seq, flags, eapol_pdu_size,
|
||||
trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -267,10 +287,13 @@ static void auth_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot,
|
|||
|
||||
if (result == SEC_RESULT_OK) {
|
||||
data->tls_result = EAP_TLS_RESULT_HANDSHAKE_OVER;
|
||||
tr_info("EAP-TLS: handshake success");
|
||||
} else if (result == SEC_RESULT_CONF_ERROR) {
|
||||
data->tls_result = EAP_TLS_RESULT_HANDSHAKE_FATAL_ERROR;
|
||||
tr_error("EAP-TLS: handshake fatal error");
|
||||
} else {
|
||||
data->tls_result = EAP_TLS_RESULT_HANDSHAKE_FAILED;
|
||||
tr_error("EAP-TLS: handshake failed");
|
||||
}
|
||||
|
||||
data->tls_ongoing = false;
|
||||
|
@ -328,12 +351,7 @@ static void auth_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
|
|||
|
||||
static void auth_eap_tls_sec_prot_delete_tls(sec_prot_t *prot)
|
||||
{
|
||||
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||
// If initialized, TLS terminates on its own
|
||||
if (data->tls_prot) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Triggers TLS to terminate if it is not already terminating by its own
|
||||
sec_prot_t *tls_prot = prot->type_get(prot, SEC_PROT_TYPE_TLS);
|
||||
if (tls_prot) {
|
||||
tls_prot->finished_send(tls_prot);
|
||||
|
@ -353,7 +371,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
|
||||
// Wait KMP-CREATE.request
|
||||
case EAP_TLS_STATE_CREATE_REQ:
|
||||
tr_debug("EAP-TLS start");
|
||||
tr_info("EAP-TLS start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
prot->timer_start(prot);
|
||||
|
||||
|
@ -387,9 +405,6 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
return;
|
||||
}
|
||||
|
||||
// Increment sequence ID
|
||||
//auth_eap_tls_sec_prot_seq_id_update(prot);
|
||||
|
||||
// Sends EAP request, TLS EAP start
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START);
|
||||
|
||||
|
@ -477,6 +492,8 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
} else {
|
||||
// TLS done, indicate success to peer
|
||||
if (data->tls_result == EAP_TLS_RESULT_HANDSHAKE_OVER) {
|
||||
// Supplicant PMK is now valid
|
||||
sec_prot_keys_pmk_mismatch_reset(prot->sec_keys);
|
||||
// Sends EAP success
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_SUCCESS, 0, EAP_TLS_EXCHANGE_NONE);
|
||||
} else {
|
||||
|
@ -491,13 +508,12 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
break;
|
||||
|
||||
case EAP_TLS_STATE_FINISH:
|
||||
tr_debug("EAP-TLS finish");
|
||||
tr_info("EAP-TLS finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
|
||||
|
||||
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISHED);
|
||||
data->common.ticks = 10 * 10;
|
||||
break;
|
||||
|
||||
case EAP_TLS_STATE_FINISHED:
|
||||
|
|
|
@ -88,6 +88,7 @@ int8_t eap_tls_sec_prot_lib_message_handle(uint8_t *data, uint16_t length, bool
|
|||
// Handles the length field
|
||||
if (data[0] & EAP_TLS_FRAGMENT_LENGTH) {
|
||||
if (length < 5) {
|
||||
tr_error("EAP-TLS: decode error");
|
||||
return EAP_TLS_MSG_DECODE_ERROR;
|
||||
}
|
||||
|
||||
|
@ -138,19 +139,16 @@ int8_t eap_tls_sec_prot_lib_message_handle(uint8_t *data, uint16_t length, bool
|
|||
return result;
|
||||
}
|
||||
|
||||
uint8_t *eap_tls_sec_prot_lib_message_build(uint8_t eap_code, uint8_t eap_type, uint8_t flags, uint8_t eap_id_seq, uint8_t header_size, tls_data_t *tls_send, uint16_t *length)
|
||||
uint8_t *eap_tls_sec_prot_lib_message_build(uint8_t eap_code, uint8_t eap_type, uint8_t *flags, uint8_t eap_id_seq, uint8_t header_size, tls_data_t *tls_send, uint16_t *length)
|
||||
{
|
||||
uint16_t eap_len = 4;
|
||||
uint8_t *data_ptr = NULL;
|
||||
|
||||
// Write EAP-TLS data (from EAP-TLS flags field onward)
|
||||
if (tls_send->data) {
|
||||
data_ptr = eap_tls_sec_prot_lib_fragment_write(tls_send->data + TLS_HEAD_LEN, tls_send->total_len, tls_send->handled_len, &eap_len, &flags);
|
||||
data_ptr = eap_tls_sec_prot_lib_fragment_write(tls_send->data + TLS_HEAD_LEN, tls_send->total_len, tls_send->handled_len, &eap_len, flags);
|
||||
}
|
||||
|
||||
tr_debug("send EAP %s type %s id %i flags %x len %i", eap_msg_trace[eap_code - 1],
|
||||
eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", eap_id_seq, flags, eap_len);
|
||||
|
||||
eapol_pdu_t eapol_pdu;
|
||||
|
||||
*length = eapol_pdu_eap_frame_init(&eapol_pdu, eap_code, eap_id_seq, eap_type, eap_len, data_ptr);
|
||||
|
|
|
@ -117,6 +117,6 @@ int8_t eap_tls_sec_prot_lib_message_handle(uint8_t *data, uint16_t length, bool
|
|||
* \return pointer to message to be sent or NULL in case of failure
|
||||
*
|
||||
*/
|
||||
uint8_t *eap_tls_sec_prot_lib_message_build(uint8_t eap_code, uint8_t eap_type, uint8_t flags, uint8_t eap_id_seq, uint8_t header_size, tls_data_t *tls_send, uint16_t *length);
|
||||
uint8_t *eap_tls_sec_prot_lib_message_build(uint8_t eap_code, uint8_t eap_type, uint8_t *flags, uint8_t eap_id_seq, uint8_t header_size, tls_data_t *tls_send, uint16_t *length);
|
||||
|
||||
#endif /* EAP_TLS_SEC_PROT_H_ */
|
||||
|
|
|
@ -53,12 +53,16 @@ typedef enum {
|
|||
EAP_TLS_STATE_FINISHED = SEC_STATE_FINISHED
|
||||
} eap_tls_sec_prot_state_e;
|
||||
|
||||
// Filters EAP re-transmission bursts that arrive with same EAP sequence number
|
||||
#define BURST_FILTER_TIMER_TIMEOUT 5 * 10
|
||||
|
||||
typedef struct {
|
||||
sec_prot_common_t common; /**< Common data */
|
||||
sec_prot_t *tls_prot; /**< TLS security protocol */
|
||||
eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */
|
||||
tls_data_t tls_send; /**< EAP-TLS send buffer */
|
||||
tls_data_t tls_recv; /**< EAP-TLS receive buffer */
|
||||
uint16_t burst_filt_timer; /**< Burst filter timer */
|
||||
uint8_t eap_id_seq; /**< EAP sequence */
|
||||
uint8_t eap_code; /**< Received EAP code */
|
||||
uint8_t eap_type; /**< Received EAP type */
|
||||
|
@ -72,7 +76,7 @@ static const trickle_params_t eap_tls_trickle_params = {
|
|||
.Imin = 200, /* 20s; ticks are 100ms */
|
||||
.Imax = 450, /* 45s */
|
||||
.k = 0, /* infinity - no consistency checking */
|
||||
.TimerExpirations = 4
|
||||
.TimerExpirations = 2
|
||||
};
|
||||
|
||||
static uint16_t supp_eap_tls_sec_prot_size(void);
|
||||
|
@ -127,6 +131,7 @@ static int8_t supp_eap_tls_sec_prot_init(sec_prot_t *prot)
|
|||
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_INIT);
|
||||
|
||||
data->tls_prot = NULL;
|
||||
data->burst_filt_timer = 0;
|
||||
data->eap_id_seq = 0;
|
||||
data->eap_code = 0;
|
||||
data->eap_type = 0;
|
||||
|
@ -186,15 +191,30 @@ static int8_t supp_eap_tls_sec_prot_message_handle(sec_prot_t *prot)
|
|||
uint8_t *data_ptr = data->recv_eapol_pdu.msg.eap.data_ptr;
|
||||
uint16_t length = data->recv_eapol_pdu.msg.eap.length;
|
||||
|
||||
uint8_t new_seq_id = false;
|
||||
if (data->recv_eapol_pdu.msg.eap.id_seq > data->eap_id_seq) {
|
||||
new_seq_id = true;
|
||||
}
|
||||
|
||||
tr_debug("recv EAP %s type %s id %i flags %x len %i", eap_msg_trace[data->eap_code - 1],
|
||||
tr_info("EAP-TLS recv %s type %s id %i flags %x len %i", eap_msg_trace[data->eap_code - 1],
|
||||
data->eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->recv_eapol_pdu.msg.eap.id_seq,
|
||||
length >= 6 ? data_ptr[0] : 0, length);
|
||||
|
||||
uint8_t new_seq_id = false;
|
||||
// New sequence identifier received
|
||||
if (data->recv_eapol_pdu.msg.eap.id_seq > data->eap_id_seq) {
|
||||
data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT;
|
||||
new_seq_id = true;
|
||||
} else if (data->recv_eapol_pdu.msg.eap.id_seq == data->eap_id_seq) {
|
||||
if (data->burst_filt_timer > 0) {
|
||||
/* If retransmission arrives when burst filter timer is running, ignores it
|
||||
and starts timer again */
|
||||
data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT;
|
||||
return EAP_TLS_MSG_DECODE_ERROR;
|
||||
} else {
|
||||
// If retransmission arrives after timeout, starts timer again
|
||||
data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT;
|
||||
}
|
||||
} else if (data->recv_eapol_pdu.msg.eap.id_seq < data->eap_id_seq) {
|
||||
// Already received sequence ID is received again, ignore
|
||||
return EAP_TLS_MSG_DECODE_ERROR;
|
||||
}
|
||||
|
||||
if (data->eap_type == EAP_IDENTITY) {
|
||||
return EAP_TLS_MSG_IDENTITY;
|
||||
}
|
||||
|
@ -233,11 +253,14 @@ static int8_t supp_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_c
|
|||
}
|
||||
|
||||
uint16_t eapol_pdu_size;
|
||||
uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, flags, data->eap_id_seq, prot->header_size, &data->tls_send, &eapol_pdu_size);
|
||||
uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, &flags, data->eap_id_seq, prot->header_size, &data->tls_send, &eapol_pdu_size);
|
||||
if (!eapol_decoded_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_info("EAP-TLS: send %s type %s id %i flags %x len %i", eap_msg_trace[eap_code - 1],
|
||||
eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->eap_id_seq, flags, eapol_pdu_size);
|
||||
|
||||
if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -248,6 +271,13 @@ static int8_t supp_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_c
|
|||
static void supp_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||
{
|
||||
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||
|
||||
if (data->burst_filt_timer > ticks) {
|
||||
data->burst_filt_timer -= ticks;
|
||||
} else {
|
||||
data->burst_filt_timer = 0;
|
||||
}
|
||||
|
||||
sec_prot_timer_timeout_handle(prot, &data->common, &eap_tls_trickle_params, ticks);
|
||||
}
|
||||
|
||||
|
@ -278,11 +308,14 @@ static void supp_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot,
|
|||
|
||||
if (result == SEC_RESULT_OK) {
|
||||
data->tls_result = EAP_TLS_RESULT_HANDSHAKE_OVER;
|
||||
tr_info("EAP-TLS: handshake success");
|
||||
} else if (result == SEC_RESULT_CONF_ERROR) {
|
||||
data->tls_result = EAP_TLS_RESULT_HANDSHAKE_FATAL_ERROR;
|
||||
tr_error("EAP-TLS: handshake fatal error");
|
||||
} else {
|
||||
// On failure has sent ALERT
|
||||
data->tls_result = EAP_TLS_RESULT_HANDSHAKE_FAILED;
|
||||
tr_error("EAP-TLS: handshake failed");
|
||||
}
|
||||
|
||||
data->tls_ongoing = false;
|
||||
|
@ -340,12 +373,7 @@ static void supp_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
|
|||
|
||||
static void supp_eap_tls_sec_prot_delete_tls(sec_prot_t *prot)
|
||||
{
|
||||
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||
// If initialized, TLS terminates on its own
|
||||
if (data->tls_prot) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Triggers TLS to terminate if it is not already terminating by its own
|
||||
sec_prot_t *tls_prot = prot->type_get(prot, SEC_PROT_TYPE_TLS);
|
||||
if (tls_prot) {
|
||||
tls_prot->finished_send(tls_prot);
|
||||
|
@ -374,7 +402,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
// Store sequence ID
|
||||
supp_eap_tls_sec_prot_seq_id_update(prot);
|
||||
|
||||
tr_debug("EAP-TLS start");
|
||||
tr_info("EAP-TLS start");
|
||||
|
||||
prot->timer_start(prot);
|
||||
|
||||
|
@ -402,8 +430,8 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
case EAP_TLS_STATE_REQUEST_TLS_EAP:
|
||||
// On timeout
|
||||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
// Re-send EAP response, Identity
|
||||
supp_eap_tls_sec_prot_message_send(prot, EAP_RESPONSE, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
|
||||
/* Waits for next trickle expire. If trickle expirations reach the limit,
|
||||
terminates EAP-TLS */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -435,8 +463,8 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
case EAP_TLS_STATE_REQUEST:
|
||||
// On timeout
|
||||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
// Re-send EAP response
|
||||
supp_eap_tls_sec_prot_message_send(prot, EAP_RESPONSE, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING);
|
||||
/* Waits for next trickle expire. If trickle expirations reach the limit,
|
||||
terminates EAP-TLS */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -488,7 +516,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
break;
|
||||
|
||||
case EAP_TLS_STATE_FINISH:
|
||||
tr_debug("EAP-TLS finish");
|
||||
tr_info("EAP-TLS finish");
|
||||
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
|
||||
|
|
|
@ -155,12 +155,18 @@ static int8_t auth_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
|
|||
// Get message
|
||||
data->recv_msg = auth_fwh_sec_prot_message_get(&data->recv_eapol_pdu, prot->sec_keys);
|
||||
if (data->recv_msg != FWH_MESSAGE_UNKNOWN) {
|
||||
tr_info("4WH: recv %s, eui-64: %s", data->recv_msg == FWH_MESSAGE_2 ? "Message 2" : "Message 4", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// Call state machine
|
||||
data->recv_pdu = pdu;
|
||||
data->recv_size = size;
|
||||
prot->state_machine(prot);
|
||||
} else {
|
||||
tr_error("4WH: recv error, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
}
|
||||
ret_val = 0;
|
||||
} else {
|
||||
tr_error("4WH: recv error, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
}
|
||||
|
||||
memset(&data->recv_eapol_pdu, 0, sizeof(eapol_pdu_t));
|
||||
|
@ -180,7 +186,7 @@ static fwh_sec_prot_msg_e auth_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu,
|
|||
return FWH_MESSAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
uint8_t key_mask = sec_prot_lib_key_mask_get(eapol_pdu);
|
||||
uint8_t key_mask = eapol_pdu_key_mask_get(eapol_pdu);
|
||||
|
||||
switch (key_mask) {
|
||||
case KEY_INFO_KEY_MIC:
|
||||
|
@ -241,14 +247,14 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
break;
|
||||
case FWH_MESSAGE_3: {
|
||||
uint8_t gtk_index;
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(prot->sec_keys->gtks, >k_index);
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(prot->sec_keys, >k_index);
|
||||
if (gtk) {
|
||||
kde_end = kde_gtk_write(kde_end, gtk_index, gtk);
|
||||
|
||||
uint32_t gtk_lifetime = sec_prot_keys_gtk_lifetime_get(prot->sec_keys->gtks, gtk_index);
|
||||
kde_end = kde_lifetime_write(kde_end, gtk_lifetime);
|
||||
}
|
||||
uint8_t gtkl = sec_prot_keys_gtkl_get(prot->sec_keys->gtks);
|
||||
uint8_t gtkl = sec_prot_keys_fresh_gtkl_get(prot->sec_keys->gtks);
|
||||
kde_end = kde_gtkl_write(kde_end, gtkl);
|
||||
kde_padding_write(kde_end, kde_start + kde_len);
|
||||
}
|
||||
|
@ -267,7 +273,7 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
sec_prot_keys_pmk_replay_cnt_increment(prot->sec_keys);
|
||||
eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys);
|
||||
eapol_pdu.msg.key.key_information.key_ack = true;
|
||||
eapol_pdu.msg.key.key_length = 32;
|
||||
eapol_pdu.msg.key.key_length = EAPOL_KEY_LEN;
|
||||
eapol_pdu.msg.key.key_nonce = data->nonce;
|
||||
break;
|
||||
case FWH_MESSAGE_3:
|
||||
|
@ -279,7 +285,7 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
eapol_pdu.msg.key.key_information.secured_key_frame = true;
|
||||
eapol_pdu.msg.key.key_information.encrypted_key_data = true;
|
||||
eapol_pdu.msg.key.key_nonce = data->nonce;
|
||||
eapol_pdu.msg.key.key_length = 32;
|
||||
eapol_pdu.msg.key.key_length = EAPOL_KEY_LEN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -293,6 +299,8 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("4WH: send %s, eui-64: %s", msg == FWH_MESSAGE_1 ? "Message 1" : "Message 3", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -319,7 +327,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
|
||||
// Wait KMP-CREATE.request
|
||||
case FWH_STATE_CREATE_REQ:
|
||||
tr_debug("4WH start");
|
||||
tr_info("4WH: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
uint8_t *pmk = sec_prot_keys_pmk_get(prot->sec_keys);
|
||||
if (!pmk) { // If PMK is not set fails
|
||||
|
@ -383,13 +391,18 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
return;
|
||||
}
|
||||
|
||||
// If GTK was inserted set it valid
|
||||
sec_prot_keys_gtkl_from_gtk_insert_index_set(prot->sec_keys);
|
||||
// Reset PTK mismatch
|
||||
sec_prot_keys_ptk_mismatch_reset(prot->sec_keys);
|
||||
// Update PTK
|
||||
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk);
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
|
||||
}
|
||||
break;
|
||||
|
||||
case FWH_STATE_FINISH:
|
||||
tr_debug("4WH finish");
|
||||
tr_info("4WH: finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), 0);
|
||||
|
@ -417,6 +430,7 @@ static int8_t auth_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *
|
|||
|
||||
uint8_t *remote_nonce = data->recv_eapol_pdu.msg.key.key_nonce;
|
||||
if (!remote_nonce) {
|
||||
tr_error("SNonce invalid");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef enum {
|
|||
FWH_STATE_CREATE_IND = SEC_STATE_CREATE_IND,
|
||||
FWH_STATE_MESSAGE_1 = SEC_STATE_FIRST,
|
||||
FWH_STATE_MESSAGE_3,
|
||||
FWH_STATE_MESSAGE_3_RETRY_WAIT,
|
||||
FWH_STATE_CREATE_RESP_SUPP_RETRY,
|
||||
FWH_STATE_FINISH = SEC_STATE_FINISH,
|
||||
FWH_STATE_FINISHED = SEC_STATE_FINISHED
|
||||
|
@ -76,22 +77,18 @@ typedef struct {
|
|||
void *recv_pdu; /**< received pdu */
|
||||
uint16_t recv_size; /**< received pdu size */
|
||||
uint64_t recv_replay_cnt; /**< received replay counter */
|
||||
bool msg3_received : 1; /**< Valid Message 3 has been received */
|
||||
bool msg3_retry_wait : 1; /**< Waiting for Message 3 retry */
|
||||
bool recv_replay_cnt_set : 1; /**< received replay counter set */
|
||||
} fwh_sec_prot_int_t;
|
||||
|
||||
static const trickle_params_t fwh_trickle_params = {
|
||||
.Imin = 50, /* 5000ms; ticks are 100ms */
|
||||
.Imax = 150, /* 15000ms */
|
||||
.k = 0, /* infinity - no consistency checking */
|
||||
.TimerExpirations = 4
|
||||
};
|
||||
|
||||
static uint16_t supp_fwh_sec_prot_size(void);
|
||||
static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot);
|
||||
|
||||
static void supp_fwh_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result);
|
||||
static void supp_fwh_sec_prot_delete(sec_prot_t *prot);
|
||||
static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
|
||||
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys);
|
||||
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(sec_prot_t *prot, eapol_pdu_t *eapol_pdu);
|
||||
static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot);
|
||||
|
||||
static int8_t supp_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg);
|
||||
|
@ -101,6 +98,7 @@ static int8_t supp_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *
|
|||
static int8_t supp_fwh_sec_prot_mic_validate(sec_prot_t *prot);
|
||||
|
||||
static void supp_fwh_sec_prot_recv_replay_counter_store(sec_prot_t *prot);
|
||||
static bool supp_fwh_sec_prot_recv_replay_cnt_compare(uint64_t received_counter, sec_prot_t *prot);
|
||||
static void supp_fwh_sec_prot_anonce_store(sec_prot_t *prot);
|
||||
static int8_t supp_fwh_sec_prot_anonce_validate(sec_prot_t *prot);
|
||||
static void supp_fwh_sec_prot_security_replay_counter_update(sec_prot_t *prot);
|
||||
|
@ -141,6 +139,10 @@ static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot)
|
|||
sec_prot_state_set(prot, &data->common, FWH_STATE_INIT);
|
||||
|
||||
data->common.ticks = 30 * 10; // 30 seconds
|
||||
data->msg3_received = false;
|
||||
data->msg3_retry_wait = false;
|
||||
data->recv_replay_cnt = 0;
|
||||
data->recv_replay_cnt_set = false;
|
||||
|
||||
uint8_t eui64[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
sec_prot_lib_nonce_init(data->snonce, eui64, 1000);
|
||||
|
@ -171,14 +173,20 @@ static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
|
|||
// Decoding is successful
|
||||
if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) {
|
||||
// Get message
|
||||
data->recv_msg = supp_fwh_sec_prot_message_get(&data->recv_eapol_pdu, prot->sec_keys);
|
||||
data->recv_msg = supp_fwh_sec_prot_message_get(prot, &data->recv_eapol_pdu);
|
||||
if (data->recv_msg != FWH_MESSAGE_UNKNOWN) {
|
||||
tr_info("4WH: recv %s", data->recv_msg == FWH_MESSAGE_1 ? "Message 1" : "Message 3");
|
||||
|
||||
// Call state machine
|
||||
data->recv_pdu = pdu;
|
||||
data->recv_size = size;
|
||||
prot->state_machine(prot);
|
||||
} else {
|
||||
tr_error("4WH: recv error");
|
||||
}
|
||||
ret_val = 0;
|
||||
} else {
|
||||
tr_error("4WH: recv error");
|
||||
}
|
||||
|
||||
memset(&data->recv_eapol_pdu, 0, sizeof(eapol_pdu_t));
|
||||
|
@ -189,7 +197,7 @@ static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys)
|
||||
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(sec_prot_t *prot, eapol_pdu_t *eapol_pdu)
|
||||
{
|
||||
fwh_sec_prot_msg_e msg = FWH_MESSAGE_UNKNOWN;
|
||||
|
||||
|
@ -198,23 +206,33 @@ static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu,
|
|||
return FWH_MESSAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
uint8_t key_mask = sec_prot_lib_key_mask_get(eapol_pdu);
|
||||
uint8_t key_mask = eapol_pdu_key_mask_get(eapol_pdu);
|
||||
|
||||
switch (key_mask) {
|
||||
// Message 1
|
||||
case KEY_INFO_KEY_ACK:
|
||||
// Must have valid replay counter
|
||||
if (eapol_pdu->msg.key.replay_counter > sec_prot_keys_pmk_replay_cnt_get(sec_keys)) {
|
||||
/* Must have valid replay counter, both larger for PMK and larger that is used on
|
||||
* the four way handshake session (note: PMK replay counter is not updated for Message 1
|
||||
* but session specific counter is)
|
||||
*/
|
||||
if (sec_prot_keys_pmk_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, prot->sec_keys) &&
|
||||
supp_fwh_sec_prot_recv_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, prot)) {
|
||||
msg = FWH_MESSAGE_1;
|
||||
} else {
|
||||
tr_error("4WH: invalid replay counter %"PRId64, eapol_pdu->msg.key.replay_counter);
|
||||
}
|
||||
break;
|
||||
// Message 3
|
||||
case KEY_INFO_INSTALL | KEY_INFO_KEY_ACK | KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME:
|
||||
// Must have valid replay counter
|
||||
if (eapol_pdu->msg.key.replay_counter > sec_prot_keys_pmk_replay_cnt_get(sec_keys)) {
|
||||
if (sec_prot_keys_pmk_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, prot->sec_keys)) {
|
||||
if (eapol_pdu->msg.key.key_information.encrypted_key_data) {
|
||||
// This should include the GTK KDE, Lifetime KDE and GTKL KDE.
|
||||
// At least some of them should be present
|
||||
msg = FWH_MESSAGE_3;
|
||||
}
|
||||
} else {
|
||||
tr_error("4WH: invalid replay counter %"PRId64, eapol_pdu->msg.key.replay_counter);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -256,6 +274,8 @@ static int8_t supp_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("4WH: send %s", msg == FWH_MESSAGE_2 ? "Message 2" : "Message 4");
|
||||
|
||||
if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -266,7 +286,7 @@ static int8_t supp_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
static void supp_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||
{
|
||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||
sec_prot_timer_timeout_handle(prot, &data->common, &fwh_trickle_params, ticks);
|
||||
sec_prot_timer_timeout_handle(prot, &data->common, NULL, ticks);
|
||||
}
|
||||
|
||||
static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||
|
@ -291,7 +311,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
return;
|
||||
}
|
||||
|
||||
tr_debug("4WH start");
|
||||
tr_info("4WH: start");
|
||||
|
||||
// Store authenticator nonce for check when 4WH Message 3 is received
|
||||
supp_fwh_sec_prot_anonce_store(prot);
|
||||
|
@ -335,9 +355,13 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
if (supp_fwh_sec_prot_ptk_generate(prot, prot->sec_keys) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
supp_fwh_sec_prot_recv_replay_counter_store(prot);
|
||||
|
||||
// Send 4WH message 2
|
||||
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
|
||||
data->common.ticks = 30 * 10; // 30 seconds
|
||||
return;
|
||||
} else if (data->recv_msg != FWH_MESSAGE_3) {
|
||||
return;
|
||||
}
|
||||
|
@ -359,6 +383,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
|
||||
supp_fwh_sec_prot_recv_replay_counter_store(prot);
|
||||
supp_fwh_sec_prot_security_replay_counter_update(prot);
|
||||
data->msg3_received = true;
|
||||
|
||||
// Sends 4WH Message 4
|
||||
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
|
||||
|
@ -367,19 +392,37 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
break;
|
||||
|
||||
case FWH_STATE_FINISH:
|
||||
tr_debug("4WH finish");
|
||||
if (data->msg3_retry_wait) {
|
||||
tr_info("4WH: Message 3 retry timeout");
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
|
||||
return;
|
||||
}
|
||||
|
||||
// If Message 3 has been received updates key data and waits for Message 3 retry
|
||||
if (data->msg3_received) {
|
||||
data->msg3_retry_wait = true;
|
||||
|
||||
tr_info("4WH: finish, wait Message 3 retry");
|
||||
|
||||
// KMP-FINISHED.indication
|
||||
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk);
|
||||
sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
|
||||
|
||||
data->common.ticks = 60 * 10; // 60 seconds
|
||||
// KMP-FINISHED.indication
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3_RETRY_WAIT);
|
||||
} else {
|
||||
tr_info("4WH: finish");
|
||||
// KMP-FINISHED.indication
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
|
||||
}
|
||||
break;
|
||||
|
||||
case FWH_STATE_FINISHED:
|
||||
case FWH_STATE_MESSAGE_3_RETRY_WAIT:
|
||||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
prot->timer_stop(prot);
|
||||
prot->finished(prot);
|
||||
tr_info("4WH: Message 3 retry timeout");
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
|
||||
} else {
|
||||
if (data->recv_msg != FWH_MESSAGE_3) {
|
||||
return;
|
||||
|
@ -403,25 +446,15 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
supp_fwh_sec_prot_recv_replay_counter_store(prot);
|
||||
supp_fwh_sec_prot_security_replay_counter_update(prot);
|
||||
|
||||
tr_debug("4WH start again");
|
||||
tr_info("4WH: send Message 4 again");
|
||||
|
||||
// Send KMP-CREATE.indication
|
||||
prot->create_ind(prot);
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_CREATE_RESP_SUPP_RETRY);
|
||||
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
|
||||
}
|
||||
break;
|
||||
|
||||
// Special case for second receiving of 4WH message 3
|
||||
case FWH_STATE_CREATE_RESP_SUPP_RETRY:
|
||||
if (sec_prot_result_ok_check(&data->common)) {
|
||||
// Send 4WH message 4
|
||||
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
|
||||
data->common.ticks = 30 * 10; // 30 seconds
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
|
||||
} else {
|
||||
// Ready to be deleted
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
|
||||
}
|
||||
case FWH_STATE_FINISHED:
|
||||
prot->timer_stop(prot);
|
||||
prot->finished(prot);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -438,7 +471,8 @@ static int8_t supp_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *
|
|||
|
||||
uint8_t *remote_nonce = data->recv_eapol_pdu.msg.key.key_nonce;
|
||||
if (!remote_nonce) {
|
||||
return 1;
|
||||
tr_error("No ANonce");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
|
||||
|
@ -457,6 +491,21 @@ static void supp_fwh_sec_prot_recv_replay_counter_store(sec_prot_t *prot)
|
|||
{
|
||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||
data->recv_replay_cnt = data->recv_eapol_pdu.msg.key.replay_counter;
|
||||
data->recv_replay_cnt_set = true;
|
||||
}
|
||||
|
||||
static bool supp_fwh_sec_prot_recv_replay_cnt_compare(uint64_t received_counter, sec_prot_t *prot)
|
||||
{
|
||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||
// If previous value is set must be greater
|
||||
if (data->recv_replay_cnt_set && received_counter > data->recv_replay_cnt) {
|
||||
return true;
|
||||
} else if (!data->recv_replay_cnt_set && received_counter >= data->recv_replay_cnt) {
|
||||
// Otherwise allows also same value e.g. zero
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void supp_fwh_sec_prot_anonce_store(sec_prot_t *prot)
|
||||
|
@ -469,6 +518,7 @@ static int8_t supp_fwh_sec_prot_anonce_validate(sec_prot_t *prot)
|
|||
{
|
||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||
if (memcmp(data->anonce, data->recv_eapol_pdu.msg.key.key_nonce, EAPOL_KEY_NONCE_LEN) != 0) {
|
||||
tr_error("ANonce invalid");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -508,7 +558,7 @@ static int8_t supp_fwh_kde_handle(sec_prot_t *prot)
|
|||
|
||||
case FWH_MESSAGE_3:
|
||||
// If a valid new GTK value present, insert it
|
||||
if (sec_prot_lib_gtk_read(kde, kde_len, prot->sec_keys->gtks) < 0) {
|
||||
if (sec_prot_lib_gtk_read(kde, kde_len, prot->sec_keys) < 0) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
@ -521,6 +571,7 @@ static int8_t supp_fwh_kde_handle(sec_prot_t *prot)
|
|||
return 0;
|
||||
|
||||
error:
|
||||
tr_error("Invalid KDEs");
|
||||
ns_dyn_mem_free(kde);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -139,12 +139,18 @@ static int8_t auth_gkh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
|
|||
if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) {
|
||||
// Get message
|
||||
if (auth_gkh_sec_prot_message_get(&data->recv_eapol_pdu, prot->sec_keys) != GKH_MESSAGE_UNKNOWN) {
|
||||
tr_info("GKH: recv Message 2, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// Call state machine
|
||||
data->recv_pdu = pdu;
|
||||
data->recv_size = size;
|
||||
prot->state_machine(prot);
|
||||
} else {
|
||||
tr_error("GKH: recv error, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
}
|
||||
ret_val = 0;
|
||||
} else {
|
||||
tr_error("GKH: recv error, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
}
|
||||
|
||||
memset(&data->recv_eapol_pdu, 0, sizeof(eapol_pdu_t));
|
||||
|
@ -163,7 +169,7 @@ static gkh_sec_prot_msg_e auth_gkh_sec_prot_message_get(eapol_pdu_t *eapol_pdu,
|
|||
return GKH_MESSAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
uint8_t key_mask = sec_prot_lib_key_mask_get(eapol_pdu);
|
||||
uint8_t key_mask = eapol_pdu_key_mask_get(eapol_pdu);
|
||||
|
||||
switch (key_mask) {
|
||||
case KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME:
|
||||
|
@ -204,14 +210,14 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
|
|||
switch (msg) {
|
||||
case GKH_MESSAGE_1: {
|
||||
uint8_t gtk_index;
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(prot->sec_keys->gtks, >k_index);
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(prot->sec_keys, >k_index);
|
||||
if (gtk) {
|
||||
kde_end = kde_gtk_write(kde_end, gtk_index, gtk);
|
||||
|
||||
uint32_t gtk_lifetime = sec_prot_keys_gtk_lifetime_get(prot->sec_keys->gtks, gtk_index);
|
||||
kde_end = kde_lifetime_write(kde_end, gtk_lifetime);
|
||||
}
|
||||
uint8_t gtkl = sec_prot_keys_gtkl_get(prot->sec_keys->gtks);
|
||||
uint8_t gtkl = sec_prot_keys_fresh_gtkl_get(prot->sec_keys->gtks);
|
||||
kde_end = kde_gtkl_write(kde_end, gtkl);
|
||||
kde_padding_write(kde_end, kde_start + kde_len);
|
||||
}
|
||||
|
@ -245,6 +251,8 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("GKH: send Message 1, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -270,7 +278,7 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
|
||||
// Wait KMP-CREATE.request
|
||||
case GKH_STATE_CREATE_REQ:
|
||||
tr_debug("GKH start");
|
||||
tr_info("GKH start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
prot->timer_start(prot);
|
||||
|
||||
|
@ -296,12 +304,15 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
if (auth_gkh_sec_prot_mic_validate(prot) < 0) {
|
||||
return;
|
||||
}
|
||||
// Set inserted GTK valid
|
||||
sec_prot_keys_gtkl_from_gtk_insert_index_set(prot->sec_keys);
|
||||
|
||||
sec_prot_state_set(prot, &data->common, GKH_STATE_FINISH);
|
||||
}
|
||||
break;
|
||||
|
||||
case GKH_STATE_FINISH:
|
||||
tr_debug("GKH finish");
|
||||
tr_info("GKH finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), 0);
|
||||
|
|
|
@ -142,12 +142,18 @@ static int8_t supp_gkh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
|
|||
if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) {
|
||||
// Get message
|
||||
if (supp_gkh_sec_prot_message_get(&data->recv_eapol_pdu, prot->sec_keys) != GKH_MESSAGE_UNKNOWN) {
|
||||
tr_info("GKH: recv Message 1");
|
||||
|
||||
// Call state machine
|
||||
data->recv_pdu = pdu;
|
||||
data->recv_size = size;
|
||||
prot->state_machine(prot);
|
||||
} else {
|
||||
tr_error("GKH: recv error");
|
||||
}
|
||||
ret_val = 0;
|
||||
} else {
|
||||
tr_error("GKH: recv error");
|
||||
}
|
||||
|
||||
memset(&data->recv_eapol_pdu, 0, sizeof(eapol_pdu_t));
|
||||
|
@ -166,16 +172,18 @@ static gkh_sec_prot_msg_e supp_gkh_sec_prot_message_get(eapol_pdu_t *eapol_pdu,
|
|||
return GKH_MESSAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
uint8_t key_mask = sec_prot_lib_key_mask_get(eapol_pdu);
|
||||
uint8_t key_mask = eapol_pdu_key_mask_get(eapol_pdu);
|
||||
|
||||
switch (key_mask) {
|
||||
case KEY_INFO_KEY_ACK | KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME:
|
||||
// Must have valid replay counter
|
||||
if (eapol_pdu->msg.key.replay_counter > sec_prot_keys_pmk_replay_cnt_get(sec_keys)) {
|
||||
if (sec_prot_keys_pmk_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, sec_keys)) {
|
||||
if (eapol_pdu->msg.key.key_information.encrypted_key_data) {
|
||||
// This should include the GTK KDE, Lifetime KDE and GTKL KDE.
|
||||
msg = GKH_MESSAGE_1;
|
||||
}
|
||||
} else {
|
||||
tr_error("GKH: invalid replay counter %"PRId64, eapol_pdu->msg.key.replay_counter);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -207,6 +215,8 @@ static int8_t supp_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("GKH: send Message 2");
|
||||
|
||||
if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -304,15 +314,11 @@ static int8_t supp_gkh_kde_handle(sec_prot_t *prot)
|
|||
}
|
||||
|
||||
// If a valid new GTK value present, insert it
|
||||
int8_t ret = sec_prot_lib_gtk_read(kde, kde_len, prot->sec_keys->gtks);
|
||||
int8_t ret = sec_prot_lib_gtk_read(kde, kde_len, prot->sec_keys);
|
||||
|
||||
ns_dyn_mem_free(kde);
|
||||
|
||||
if (ret < 0 || sec_prot_keys_gtk_insert_index_get(prot->sec_keys->gtks) < 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
|
@ -113,13 +113,23 @@ static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_k
|
|||
uint16_t kde_len = KDE_GTKL_LEN;
|
||||
|
||||
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
|
||||
uint8_t pmkid[PMKID_LEN];
|
||||
if (pmk) {
|
||||
if (sec_prot_lib_pmkid_generate(prot, pmkid, false) >= 0) {
|
||||
kde_len += KDE_PMKID_LEN;
|
||||
} else {
|
||||
pmk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *ptk = sec_prot_keys_ptk_get(sec_keys);
|
||||
uint8_t ptkid[PTKID_LEN];
|
||||
if (ptk) {
|
||||
if (sec_prot_lib_ptkid_generate(prot, ptkid, false) >= 0) {
|
||||
kde_len += KDE_PTKID_LEN;
|
||||
} else {
|
||||
ptk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *kde_start = ns_dyn_mem_temporary_alloc(kde_len);
|
||||
|
@ -130,20 +140,14 @@ static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_k
|
|||
uint8_t *kde_end = kde_start;
|
||||
|
||||
if (pmk) {
|
||||
uint8_t pmkid[PMKID_LEN];
|
||||
if (sec_prot_lib_pmkid_generate(prot, pmkid, true) >= 0) {
|
||||
kde_end = kde_pmkid_write(kde_end, pmkid);
|
||||
}
|
||||
}
|
||||
|
||||
if (ptk) {
|
||||
uint8_t ptkid[PTKID_LEN];
|
||||
if (sec_prot_lib_ptkid_generate(prot, ptkid, true) >= 0) {
|
||||
kde_end = kde_ptkid_write(kde_end, ptkid);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t gtkl = sec_prot_keys_gtkl_get(sec_keys->gtks);
|
||||
uint8_t gtkl = sec_prot_keys_fresh_gtkl_get(sec_keys->gtks);
|
||||
kde_end = kde_gtkl_write(kde_end, gtkl);
|
||||
|
||||
kde_len = kde_end - kde_start;
|
||||
|
@ -157,14 +161,15 @@ static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_k
|
|||
if (!eapol_decoded_data) {
|
||||
data->result = SEC_RESULT_ERR_NO_MEM;
|
||||
} else {
|
||||
//Test Data
|
||||
eapol_pdu.msg.key.key_information.install = false;
|
||||
eapol_pdu.msg.key.key_information.pairwise_key = false;
|
||||
eapol_pdu.msg.key.key_information.request = true;
|
||||
eapol_pdu.msg.key.replay_counter = 10;
|
||||
eapol_pdu.msg.key.key_length = 32;
|
||||
eapol_pdu.msg.key.replay_counter = 0;
|
||||
eapol_pdu.msg.key.key_length = 0;
|
||||
eapol_write_pdu_frame(eapol_decoded_data + prot->header_size, &eapol_pdu);
|
||||
|
||||
tr_info("Initial EAPOL-Key send, PMKID %s PTKID %s GTKL %x", pmk ? "set" : "not set", ptk ? "set" : "not set", gtkl);
|
||||
|
||||
if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) {
|
||||
data->result = SEC_RESULT_ERR_NO_MEM;
|
||||
}
|
||||
|
@ -187,11 +192,67 @@ static void key_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e res
|
|||
static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
|
||||
{
|
||||
eapol_pdu_t eapol_pdu;
|
||||
|
||||
tr_info("Initial EAPOL-Key recv, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// Decoding is successful
|
||||
if (eapol_parse_pdu_header(pdu, size, &eapol_pdu)) {
|
||||
if (eapol_pdu.packet_type != EAPOL_KEY_TYPE) {
|
||||
tr_info("not EAPOL-Key packet");
|
||||
prot->finished(prot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t kde_len;
|
||||
uint8_t *kde = sec_prot_lib_message_handle(prot->sec_keys->ptk, &kde_len, &eapol_pdu);
|
||||
if (!kde) {
|
||||
tr_error("no KDEs");
|
||||
prot->finished(prot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Default assumption is that PMK and PTK are not valid
|
||||
prot->sec_keys->pmk_mismatch = true;
|
||||
prot->sec_keys->ptk_mismatch = true;
|
||||
|
||||
// Checks if supplicant indicates that it has valid PMK
|
||||
uint8_t remote_keyid[KEYID_LEN];
|
||||
if (kde_pmkid_read(kde, kde_len, remote_keyid) >= 0) {
|
||||
uint8_t pmkid[PMKID_LEN];
|
||||
if (sec_prot_lib_pmkid_generate(prot, pmkid, true) >= 0) {
|
||||
if (memcmp(remote_keyid, pmkid, PMKID_LEN) == 0) {
|
||||
prot->sec_keys->pmk_mismatch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if supplicant indicates that it has valid PTK
|
||||
if (kde_ptkid_read(kde, kde_len, remote_keyid) >= 0) {
|
||||
uint8_t ptkid[PTKID_LEN];
|
||||
if (sec_prot_lib_ptkid_generate(prot, ptkid, true) >= 0) {
|
||||
if (memcmp(remote_keyid, ptkid, PTKID_LEN) == 0) {
|
||||
prot->sec_keys->ptk_mismatch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the GTKL that supplicant indicates
|
||||
uint8_t gtkl;
|
||||
if (kde_gtkl_read(kde, kde_len, >kl) >= 0) {
|
||||
prot->sec_keys->gtkl = gtkl;
|
||||
} else {
|
||||
tr_error("no GTKL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_info("PMK %s PTK %s GTKL %x", prot->sec_keys->pmk_mismatch ? "not live" : "live", prot->sec_keys->ptk_mismatch ? "not live" : "live", gtkl);
|
||||
|
||||
ns_dyn_mem_free(kde);
|
||||
|
||||
prot->create_ind(prot);
|
||||
return 0;
|
||||
} else {
|
||||
tr_error("Invalid");
|
||||
// No error handling yet, indicate just that ready to be deleted
|
||||
prot->finished(prot);
|
||||
return -1;
|
||||
|
@ -208,8 +269,6 @@ static void key_sec_prot_state_machine(sec_prot_t *prot)
|
|||
// empty
|
||||
break;
|
||||
case KEY_CREATE_REQ:
|
||||
tr_debug("initial EAPOL-Key send");
|
||||
|
||||
// KMP-CREATE.confirm
|
||||
prot->create_conf(prot, data->result);
|
||||
|
||||
|
@ -221,8 +280,6 @@ static void key_sec_prot_state_machine(sec_prot_t *prot)
|
|||
prot->finished(prot);
|
||||
break;
|
||||
case KEY_CREATE_RESP:
|
||||
tr_debug("initial EAPOL-Key receive");
|
||||
|
||||
if (data->result == SEC_RESULT_OK) {
|
||||
// KMP-FINISHED.indication, no meaning for eapol-key, just completes transfer
|
||||
prot->finished_ind(prot, SEC_RESULT_OK, 0);
|
||||
|
|
|
@ -207,6 +207,18 @@ typedef void sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uin
|
|||
*/
|
||||
typedef sec_prot_t *sec_prot_by_type_get(sec_prot_t *prot, uint8_t type);
|
||||
|
||||
/**
|
||||
* sec_prot_receive_disable disables receiving of messages
|
||||
*
|
||||
* \param prot protocol
|
||||
*
|
||||
* \return security protocol or NULL
|
||||
*
|
||||
*/
|
||||
typedef void sec_prot_receive_disable(sec_prot_t *prot);
|
||||
|
||||
typedef struct sec_prot_int_data_s sec_prot_int_data_t;
|
||||
|
||||
// Security protocol data
|
||||
struct sec_prot_s {
|
||||
sec_prot_create_request *create_req; /**< Create request */
|
||||
|
@ -232,10 +244,11 @@ struct sec_prot_s {
|
|||
|
||||
sec_prot_eui64_addr_get *addr_get; /**< Gets EUI-64 addresses */
|
||||
sec_prot_by_type_get *type_get; /**< Gets security protocol by type */
|
||||
sec_prot_receive_disable *receive_disable; /**< Disable receiving of messages */
|
||||
|
||||
sec_prot_keys_t *sec_keys; /**< Security keys storage pointer */
|
||||
uint8_t header_size; /**< Header size */
|
||||
uint8_t data; /**< Protocol internal data */
|
||||
sec_prot_int_data_t *data; /**< Protocol internal data */
|
||||
};
|
||||
|
||||
#endif /* SEC_PROT_H_ */
|
||||
|
|
|
@ -71,6 +71,11 @@ void sec_prot_certs_chain_entry_init(cert_chain_entry_t *entry)
|
|||
memset(entry, 0, sizeof(cert_chain_entry_t));
|
||||
}
|
||||
|
||||
void sec_prot_certs_chain_entry_delete(cert_chain_entry_t *entry)
|
||||
{
|
||||
ns_dyn_mem_free(entry);
|
||||
}
|
||||
|
||||
int8_t sec_prot_certs_cert_set(cert_chain_entry_t *entry, uint8_t index, uint8_t *cert, uint16_t cert_len)
|
||||
{
|
||||
if (!entry || index >= SEC_PROT_CERT_CHAIN_DEPTH) {
|
||||
|
@ -127,6 +132,33 @@ void sec_prot_certs_chain_list_delete(cert_chain_list_t *chain_list)
|
|||
}
|
||||
}
|
||||
|
||||
void sec_prot_certs_chain_list_entry_delete(cert_chain_list_t *chain_list, cert_chain_entry_t *entry)
|
||||
{
|
||||
ns_list_remove(chain_list, entry);
|
||||
sec_prot_certs_chain_entry_delete(entry);
|
||||
}
|
||||
|
||||
cert_chain_entry_t *sec_prot_certs_chain_list_entry_find(cert_chain_list_t *chain_list, cert_chain_entry_t *entry)
|
||||
{
|
||||
ns_list_foreach(cert_chain_entry_t, list_entry, chain_list) {
|
||||
bool match = true;
|
||||
for (uint8_t i = 0; i < SEC_PROT_CERT_CHAIN_DEPTH; i++) {
|
||||
if (list_entry->cert_len[i] != entry->cert_len[i]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
if (memcmp(list_entry->cert[i], entry->cert[i], list_entry->cert_len[i]) != 0) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
return list_entry;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cert_revocat_list_entry_t *sec_prot_certs_revocat_list_entry_create(void)
|
||||
{
|
||||
cert_revocat_list_entry_t *entry = ns_dyn_mem_alloc(sizeof(cert_revocat_list_entry_t));
|
||||
|
@ -142,7 +174,12 @@ void sec_prot_certs_revocat_list_entry_init(cert_revocat_list_entry_t *entry)
|
|||
memset(entry, 0, sizeof(cert_revocat_list_entry_t));
|
||||
}
|
||||
|
||||
int8_t sec_prot_certs_revocat_list_set(cert_revocat_list_entry_t *entry, uint8_t *crl, uint16_t crl_len)
|
||||
void sec_prot_certs_revocat_list_entry_delete(cert_revocat_list_entry_t *entry)
|
||||
{
|
||||
ns_dyn_mem_free(entry);
|
||||
}
|
||||
|
||||
int8_t sec_prot_certs_revocat_list_set(cert_revocat_list_entry_t *entry, const uint8_t *crl, uint16_t crl_len)
|
||||
{
|
||||
if (!entry) {
|
||||
return -1;
|
||||
|
@ -154,7 +191,7 @@ int8_t sec_prot_certs_revocat_list_set(cert_revocat_list_entry_t *entry, uint8_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *sec_prot_certs_revocat_list_get(const cert_revocat_list_entry_t *entry, uint16_t *crl_len)
|
||||
const uint8_t *sec_prot_certs_revocat_list_get(const cert_revocat_list_entry_t *entry, uint16_t *crl_len)
|
||||
{
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
|
@ -168,6 +205,25 @@ void sec_prot_certs_revocat_lists_add(cert_revocat_lists_t *cert_revocat_lists,
|
|||
ns_list_add_to_end(cert_revocat_lists, entry);
|
||||
}
|
||||
|
||||
void sec_prot_certs_revocat_lists_entry_delete(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry)
|
||||
{
|
||||
ns_list_remove(cert_revocat_lists, entry);
|
||||
sec_prot_certs_revocat_list_entry_delete(entry);
|
||||
}
|
||||
|
||||
cert_revocat_list_entry_t *sec_prot_certs_revocat_lists_entry_find(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry)
|
||||
{
|
||||
ns_list_foreach_safe(cert_revocat_list_entry_t, list_entry, cert_revocat_lists) {
|
||||
if (list_entry->crl_len == entry->crl_len) {
|
||||
if (memcmp(list_entry->crl, entry->crl, list_entry->crl_len) == 0) {
|
||||
return list_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sec_prot_certs_revocat_lists_delete(cert_revocat_lists_t *cert_revocat_lists)
|
||||
{
|
||||
ns_list_foreach_safe(cert_revocat_list_entry_t, entry, cert_revocat_lists) {
|
||||
|
|
|
@ -46,7 +46,7 @@ typedef struct {
|
|||
} cert_chain_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *crl; /**< Certificate Revocation List */
|
||||
const uint8_t *crl; /**< Certificate Revocation List */
|
||||
uint16_t crl_len; /**< Certificate Revocation List length */
|
||||
ns_list_link_t link; /**< Link */
|
||||
} cert_revocat_list_entry_t;
|
||||
|
@ -92,6 +92,13 @@ cert_chain_entry_t *sec_prot_certs_chain_entry_create(void);
|
|||
*/
|
||||
void sec_prot_certs_chain_entry_init(cert_chain_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_chain_entry_delete deletes certificate chain entry
|
||||
*
|
||||
* \param entry certificate chain entry
|
||||
*/
|
||||
void sec_prot_certs_chain_entry_delete(cert_chain_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_cert_set set certificate to chain entry
|
||||
*
|
||||
|
@ -153,6 +160,26 @@ void sec_prot_certs_chain_list_add(cert_chain_list_t *cert_chain_list, cert_chai
|
|||
*/
|
||||
void sec_prot_certs_chain_list_delete(cert_chain_list_t *chain_list);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_chain_list_entry_delete deletes entry from certificate chain list
|
||||
*
|
||||
* \param cert_chain_list certificate chain entry list
|
||||
* \param entry deleted certificate chain entry
|
||||
*
|
||||
*/
|
||||
void sec_prot_certs_chain_list_entry_delete(cert_chain_list_t *chain_list, cert_chain_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_chain_list_entry_find finds entry from certificate chain list
|
||||
*
|
||||
* \param cert_chain_list certificate chain entry list
|
||||
* \param entry searched certificate chain entry
|
||||
*
|
||||
* \return certificate chain entry or NULL
|
||||
*
|
||||
*/
|
||||
cert_chain_entry_t *sec_prot_certs_chain_list_entry_find(cert_chain_list_t *chain_list, cert_chain_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_revocat_list_entry_create allocate memory for certificate revocation list entry
|
||||
*
|
||||
|
@ -167,6 +194,13 @@ cert_revocat_list_entry_t *sec_prot_certs_revocat_list_entry_create(void);
|
|||
*/
|
||||
void sec_prot_certs_revocat_list_entry_init(cert_revocat_list_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_revocat_list_entry_delete deletes certificate revocation list entry
|
||||
*
|
||||
* \param entry certificate revocation list entry
|
||||
*/
|
||||
void sec_prot_certs_revocat_list_entry_delete(cert_revocat_list_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_revocat_list_set set certificate revocation list to list entry
|
||||
*
|
||||
|
@ -177,7 +211,7 @@ void sec_prot_certs_revocat_list_entry_init(cert_revocat_list_entry_t *entry);
|
|||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*/
|
||||
int8_t sec_prot_certs_revocat_list_set(cert_revocat_list_entry_t *entry, uint8_t *crl, uint16_t crl_len);
|
||||
int8_t sec_prot_certs_revocat_list_set(cert_revocat_list_entry_t *entry, const uint8_t *crl, uint16_t crl_len);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_revocat_list_set set certificate revocation list from list entry
|
||||
|
@ -187,16 +221,35 @@ int8_t sec_prot_certs_revocat_list_set(cert_revocat_list_entry_t *entry, uint8_t
|
|||
*
|
||||
* \return pointer to crl or NULL
|
||||
*/
|
||||
uint8_t *sec_prot_certs_revocat_list_get(const cert_revocat_list_entry_t *entry, uint16_t *crl_len);
|
||||
const uint8_t *sec_prot_certs_revocat_list_get(const cert_revocat_list_entry_t *entry, uint16_t *crl_len);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_revocat_lists_add add certificate chain entry to certificate chain list
|
||||
* sec_prot_certs_revocat_lists_add add certificate revocation list entry to certificate revocation lists
|
||||
*
|
||||
* \param cert_revocat_lists certificate revocation lists
|
||||
* \param entry certificate revocation list entry
|
||||
*/
|
||||
void sec_prot_certs_revocat_lists_add(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_revocat_lists_entry_delete delete certificate revocation list entry from certificate revocation lists
|
||||
*
|
||||
* \param cert_revocat_lists certificate revocation lists
|
||||
* \param entry certificate revocation list entry
|
||||
*
|
||||
*/
|
||||
void sec_prot_certs_revocat_lists_entry_delete(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_revocat_lists_entry_find find certificate revocation list entry from certificate revocation lists
|
||||
*
|
||||
* \param cert_revocat_lists certificate revocation lists
|
||||
* \param entry certificate revocation list entry
|
||||
*
|
||||
* \return certificate revocation list entry or NULL
|
||||
*/
|
||||
cert_revocat_list_entry_t *sec_prot_certs_revocat_lists_entry_find(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry);
|
||||
|
||||
/**
|
||||
* sec_prot_certs_chain_list_delete delete certificate chain list
|
||||
*
|
||||
|
|
|
@ -25,8 +25,14 @@
|
|||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "socket_api.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "Security/kmp/kmp_addr.h"
|
||||
#include "Security/kmp/kmp_api.h"
|
||||
#include "Security/PANA/pana_eap_header.h"
|
||||
#include "Security/eapol/eapol_helper.h"
|
||||
#include "Security/protocols/sec_prot_certs.h"
|
||||
#include "Security/protocols/sec_prot_keys.h"
|
||||
#include "Security/protocols/sec_prot.h"
|
||||
#include "Security/protocols/sec_prot_lib.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
|
@ -47,13 +53,20 @@ sec_prot_keys_t *sec_prot_keys_create(sec_prot_gtk_keys_t *gtks, const sec_prot_
|
|||
void sec_prot_keys_init(sec_prot_keys_t *sec_keys, sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs)
|
||||
{
|
||||
memset(sec_keys, 0, sizeof(sec_prot_keys_t));
|
||||
sec_keys->pmk_lifetime = PMK_LIFETIME_INSTALL;
|
||||
sec_keys->ptk_lifetime = PTK_LIFETIME_INSTALL;
|
||||
sec_keys->pmk_key_replay_cnt = 0;
|
||||
sec_keys->gtks = gtks;
|
||||
sec_keys->certs = certs;
|
||||
sec_keys->gtkl = 0;
|
||||
sec_keys->gtk_set_index = -1;
|
||||
sec_keys->pmk_set = false;
|
||||
sec_keys->ptk_set = false;
|
||||
sec_keys->pmk_key_replay_cnt_set = false;
|
||||
sec_keys->updated = false;
|
||||
sec_keys->ptk_eui_64_set = false;
|
||||
sec_keys->pmk_mismatch = false;
|
||||
sec_keys->ptk_mismatch = false;
|
||||
}
|
||||
|
||||
void sec_prot_keys_delete(sec_prot_keys_t *sec_keys)
|
||||
|
@ -76,7 +89,6 @@ sec_prot_gtk_keys_t *sec_prot_keys_gtks_create(void)
|
|||
void sec_prot_keys_gtks_init(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
memset(gtks, 0, sizeof(sec_prot_gtk_keys_t));
|
||||
gtks->gtk_set_index = -1;
|
||||
gtks->updated = false;
|
||||
}
|
||||
|
||||
|
@ -89,10 +101,22 @@ void sec_prot_keys_pmk_write(sec_prot_keys_t *sec_keys, uint8_t *pmk)
|
|||
{
|
||||
memcpy(sec_keys->pmk, pmk, PMK_LEN);
|
||||
sec_keys->pmk_key_replay_cnt = 0;
|
||||
sec_keys->pmk_key_replay_cnt_set = false;
|
||||
sec_keys->pmk_lifetime = PMK_LIFETIME_INSTALL;
|
||||
sec_keys->pmk_set = true;
|
||||
sec_keys->updated = true;
|
||||
}
|
||||
|
||||
void sec_prot_keys_pmk_delete(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
memset(sec_keys->pmk, 0, PMK_LEN);
|
||||
sec_keys->pmk_key_replay_cnt = 0;
|
||||
sec_keys->pmk_key_replay_cnt_set = false;
|
||||
sec_keys->pmk_lifetime = PMK_LIFETIME_INSTALL;
|
||||
sec_keys->pmk_set = false;
|
||||
sec_keys->updated = true;
|
||||
}
|
||||
|
||||
uint8_t *sec_prot_keys_pmk_get(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
if (!sec_keys->pmk_set) {
|
||||
|
@ -109,21 +133,87 @@ uint64_t sec_prot_keys_pmk_replay_cnt_get(sec_prot_keys_t *sec_keys)
|
|||
|
||||
void sec_prot_keys_pmk_replay_cnt_set(sec_prot_keys_t *sec_keys, uint64_t counter)
|
||||
{
|
||||
sec_keys->pmk_key_replay_cnt_set = true;
|
||||
sec_keys->pmk_key_replay_cnt = counter;
|
||||
}
|
||||
|
||||
void sec_prot_keys_pmk_replay_cnt_increment(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
// Start from zero i.e. does not increment on first call
|
||||
if (!sec_keys->pmk_key_replay_cnt_set) {
|
||||
sec_keys->pmk_key_replay_cnt_set = true;
|
||||
return;
|
||||
}
|
||||
sec_keys->pmk_key_replay_cnt++;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_pmk_replay_cnt_compare(uint64_t received_counter, sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
// If previous value is set must be greater
|
||||
if (sec_keys->pmk_key_replay_cnt_set && received_counter > sec_keys->pmk_key_replay_cnt) {
|
||||
return true;
|
||||
} else if (!sec_keys->pmk_key_replay_cnt_set && received_counter >= sec_keys->pmk_key_replay_cnt) {
|
||||
// Otherwise allows also same value e.g. zero
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void sec_prot_keys_pmk_mismatch_set(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
sec_keys->pmk_mismatch = true;
|
||||
}
|
||||
|
||||
void sec_prot_keys_pmk_mismatch_reset(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
sec_keys->pmk_mismatch = false;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_pmk_mismatch_is_set(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
return sec_keys->pmk_mismatch;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_pmk_lifetime_decrement(sec_prot_keys_t *sec_keys, uint32_t default_lifetime, uint8_t seconds)
|
||||
{
|
||||
if (!sec_keys->pmk_set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sec_keys->pmk_lifetime == PMK_LIFETIME_INSTALL) {
|
||||
sec_keys->pmk_lifetime = default_lifetime;
|
||||
}
|
||||
|
||||
if (sec_keys->pmk_lifetime > seconds) {
|
||||
sec_keys->pmk_lifetime -= seconds;
|
||||
} else {
|
||||
if (sec_keys->pmk_lifetime > 0) {
|
||||
sec_keys->pmk_lifetime = 0;
|
||||
sec_prot_keys_ptk_delete(sec_keys);
|
||||
sec_prot_keys_pmk_delete(sec_keys);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void sec_prot_keys_ptk_write(sec_prot_keys_t *sec_keys, uint8_t *ptk)
|
||||
{
|
||||
memcpy(sec_keys->ptk, ptk, PTK_LEN);
|
||||
sec_keys->ptk_lifetime = PTK_LIFETIME_INSTALL;
|
||||
sec_keys->ptk_set = true;
|
||||
sec_keys->updated = true;
|
||||
}
|
||||
|
||||
void sec_prot_keys_ptk_delete(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
memset(sec_keys->ptk, 0, PTK_LEN);
|
||||
sec_keys->ptk_lifetime = PTK_LIFETIME_INSTALL;
|
||||
sec_keys->ptk_set = false;
|
||||
sec_keys->updated = true;
|
||||
}
|
||||
|
||||
uint8_t *sec_prot_keys_ptk_get(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
if (!sec_keys->ptk_set) {
|
||||
|
@ -133,29 +223,66 @@ uint8_t *sec_prot_keys_ptk_get(sec_prot_keys_t *sec_keys)
|
|||
return sec_keys->ptk;
|
||||
}
|
||||
|
||||
void sec_prot_keys_ptk_eui_64_set(sec_prot_keys_t *sec_keys, uint8_t *eui_64)
|
||||
void sec_prot_keys_ptk_mismatch_set(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
sec_keys->ptk_eui_64 = eui_64;
|
||||
sec_keys->ptk_mismatch = true;
|
||||
}
|
||||
|
||||
void sec_prot_keys_ptk_eui_64_write(sec_prot_keys_t *sec_keys, uint8_t *eui_64)
|
||||
void sec_prot_keys_ptk_mismatch_reset(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
sec_keys->ptk_mismatch = false;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_ptk_mismatch_is_set(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
return sec_keys->ptk_mismatch;
|
||||
}
|
||||
|
||||
void sec_prot_keys_ptk_eui_64_write(sec_prot_keys_t *sec_keys, const uint8_t *eui_64)
|
||||
{
|
||||
if (sec_keys->ptk_eui_64) {
|
||||
memcpy(sec_keys->ptk_eui_64, eui_64, 8);
|
||||
sec_keys->ptk_eui_64_set = true;
|
||||
sec_keys->updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *sec_prot_keys_ptk_eui_64_get(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
if (!sec_keys->ptk_eui_64 || !sec_keys->ptk_eui_64_set) {
|
||||
if (!sec_keys->ptk_eui_64_set) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sec_keys->ptk_eui_64;
|
||||
}
|
||||
|
||||
void sec_prot_keys_ptk_eui_64_delete(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
memset(sec_keys->ptk_eui_64, 0, 8);
|
||||
sec_keys->ptk_eui_64_set = false;
|
||||
sec_keys->updated = true;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_ptk_lifetime_decrement(sec_prot_keys_t *sec_keys, uint32_t default_lifetime, uint8_t seconds)
|
||||
{
|
||||
if (!sec_keys->ptk_set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sec_keys->ptk_lifetime == PTK_LIFETIME_INSTALL) {
|
||||
sec_keys->ptk_lifetime = default_lifetime;
|
||||
}
|
||||
|
||||
if (sec_keys->ptk_lifetime > seconds) {
|
||||
sec_keys->ptk_lifetime -= seconds;
|
||||
} else {
|
||||
if (sec_keys->ptk_lifetime > 0) {
|
||||
sec_prot_keys_ptk_delete(sec_keys);
|
||||
sec_keys->ptk_lifetime = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_are_updated(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
return sec_keys->updated;
|
||||
|
@ -166,82 +293,129 @@ void sec_prot_keys_updated_reset(sec_prot_keys_t *sec_keys)
|
|||
sec_keys->updated = false;
|
||||
}
|
||||
|
||||
uint8_t sec_prot_keys_gtkl_get(sec_prot_gtk_keys_t *gtks)
|
||||
uint8_t sec_prot_keys_fresh_gtkl_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
uint8_t gtkl = (uint8_t) gtks->gtk[0].live |
|
||||
(((uint8_t) gtks->gtk[1].live) << 1) |
|
||||
(((uint8_t) gtks->gtk[2].live) << 2) |
|
||||
(((uint8_t) gtks->gtk[3].live) << 3);
|
||||
uint8_t gtkl = 0;
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_status_is_live(gtks, i)) {
|
||||
gtkl |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
return gtkl;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtkl_set(sec_prot_gtk_keys_t *gtks, uint8_t gtkl)
|
||||
void sec_prot_keys_gtkl_set(sec_prot_keys_t *sec_keys, uint8_t gtkl)
|
||||
{
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (gtks->gtk[i].set) {
|
||||
if ((gtkl >> i) & 0x01) {
|
||||
gtks->gtk[i].live = true; // Live on authenticator
|
||||
} else {
|
||||
gtks->gtk[i].live = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
sec_keys->gtkl = gtkl;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_gtk_is_live(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
bool sec_prot_keys_gtkl_gtk_is_live(sec_prot_keys_t *sec_keys, uint8_t index)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].live) {
|
||||
if (index >= GTK_NUM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sec_keys->gtkl & (1 << index)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_insert_index_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
int8_t sec_prot_keys_gtkl_gtk_live_set(sec_prot_keys_t *sec_keys, uint8_t index)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].set) {
|
||||
if (index >= GTK_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gtks->gtk_set_index = index;
|
||||
sec_keys->gtkl |= (1 << index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_insert_index_get(sec_prot_gtk_keys_t *gtks)
|
||||
int8_t sec_prot_keys_gtk_insert_index_set(sec_prot_keys_t *sec_keys, uint8_t index)
|
||||
{
|
||||
return gtks->gtk_set_index;
|
||||
if (index >= GTK_NUM || !sec_keys->gtks->gtk[index].set) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec_keys->gtk_set_index = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtk_insert_index_clear(sec_prot_gtk_keys_t *gtks)
|
||||
int8_t sec_prot_keys_gtk_insert_index_get(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
gtks->gtk_set_index = -1;
|
||||
return sec_keys->gtk_set_index;
|
||||
}
|
||||
|
||||
uint8_t *sec_prot_keys_get_gtk_to_insert(sec_prot_gtk_keys_t *gtks, uint8_t *index)
|
||||
void sec_prot_keys_gtk_insert_index_clear(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
if (gtks->gtk_set_index >= 0 && gtks->gtk[gtks->gtk_set_index].set && gtks->gtk[gtks->gtk_set_index].live) {
|
||||
*index = gtks->gtk_set_index;
|
||||
return gtks->gtk[gtks->gtk_set_index].key;
|
||||
sec_keys->gtk_set_index = -1;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtkl_from_gtk_insert_index_set(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
if (sec_keys->gtk_set_index >= 0) {
|
||||
sec_prot_keys_gtkl_gtk_live_set(sec_keys, sec_keys->gtk_set_index);
|
||||
sec_prot_keys_gtk_insert_index_clear(sec_keys);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_insert_index_from_gtkl_get(sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
// Get currently active key index
|
||||
int8_t active_index = sec_prot_keys_gtk_status_active_get(sec_keys->gtks);
|
||||
|
||||
if (active_index >= 0 && !sec_prot_keys_gtkl_gtk_is_live(sec_keys, active_index)) {
|
||||
// If currently active key is not live on remote, inserts it
|
||||
sec_prot_keys_gtk_insert_index_set(sec_keys, active_index);
|
||||
return active_index;
|
||||
}
|
||||
|
||||
// Checks all keys
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_status_is_live(sec_keys->gtks, i)) {
|
||||
// If key is live, but not indicated on GTKL inserts it
|
||||
if (!sec_prot_keys_gtkl_gtk_is_live(sec_keys, i)) {
|
||||
sec_prot_keys_gtk_insert_index_set(sec_keys, i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *sec_prot_keys_get_gtk_to_insert(sec_prot_keys_t *sec_keys, uint8_t *index)
|
||||
{
|
||||
if (sec_keys->gtk_set_index >= 0 && sec_keys->gtks->gtk[sec_keys->gtk_set_index].set) {
|
||||
*index = sec_keys->gtk_set_index;
|
||||
return sec_keys->gtks->gtk[sec_keys->gtk_set_index].key;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint8_t *gtk)
|
||||
int8_t sec_prot_keys_gtk_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint8_t *gtk, uint32_t lifetime)
|
||||
{
|
||||
if (!gtk || index >= GTK_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gtks->gtk[index].set && memcmp(gtks->gtk[index].key, gtk, GTK_LEN) != 0) {
|
||||
// If same GTK is given again, do not update
|
||||
if (gtks->gtk[index].set && memcmp(gtks->gtk[index].key, gtk, GTK_LEN) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec_prot_keys_gtk_clear(gtks, index);
|
||||
uint8_t install_order = sec_prot_keys_gtk_install_order_last_get(gtks);
|
||||
|
||||
gtks->gtk[index].set = true;
|
||||
gtks->gtk[index].live = false; // Set from GTKL
|
||||
gtks->gtk[index].hash = false; // Not verified yet
|
||||
gtks->gtk[index].lifetime = 0; // Should be provided by authenticator
|
||||
gtks->gtk[index].lifetime = lifetime;
|
||||
gtks->gtk[index].status = GTK_STATUS_NEW;
|
||||
gtks->gtk[index].install_order = install_order;
|
||||
memcpy(gtks->gtk[index].key, gtk, GTK_LEN);
|
||||
|
||||
gtks->updated = true;
|
||||
|
@ -249,6 +423,22 @@ int8_t sec_prot_keys_gtk_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint8_t *
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_clear(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
{
|
||||
if (!gtks || index >= GTK_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gtks->gtk[index].set = false;
|
||||
gtks->gtk[index].lifetime = 0; // Should be provided by authenticator
|
||||
gtks->gtk[index].status = GTK_STATUS_NEW;
|
||||
memset(gtks->gtk[index].key, 0, GTK_LEN);
|
||||
|
||||
sec_prot_keys_gtk_install_order_update(gtks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_gtk_is_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].set) {
|
||||
|
@ -276,15 +466,15 @@ uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index
|
|||
return gtks->gtk[index].lifetime;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtk_lifetime_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint32_t lifetime)
|
||||
uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint16_t seconds)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].set) {
|
||||
return;
|
||||
|
||||
if (gtks->gtk[index].lifetime > seconds) {
|
||||
gtks->gtk[index].lifetime -= seconds;
|
||||
} else {
|
||||
gtks->gtk[index].lifetime = 0;
|
||||
}
|
||||
gtks->gtk[index].lifetime = lifetime;
|
||||
|
||||
gtks->updated = true;
|
||||
return gtks->gtk[index].lifetime;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_gtks_are_updated(sec_prot_gtk_keys_t *gtks)
|
||||
|
@ -302,4 +492,290 @@ void sec_prot_keys_gtks_updated_reset(sec_prot_gtk_keys_t *gtks)
|
|||
gtks->updated = false;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtk_status_fresh_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].set) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Active key remains as active, old keys are never reused
|
||||
if (gtks->gtk[index].status < GTK_STATUS_FRESH) {
|
||||
gtks->gtk[index].status = GTK_STATUS_FRESH;
|
||||
}
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtk_status_all_fresh_set(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
sec_prot_keys_gtk_status_fresh_set(gtks, i);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_status_active_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].set) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If key is valid to be taken into use sets it active
|
||||
if (gtks->gtk[index].status == GTK_STATUS_FRESH) {
|
||||
// Sets previously active key old
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
// Sets previously active key old
|
||||
if (gtks->gtk[i].status == GTK_STATUS_ACTIVE) {
|
||||
gtks->gtk[i].status = GTK_STATUS_OLD;
|
||||
}
|
||||
}
|
||||
gtks->gtk[index].status = GTK_STATUS_ACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_status_active_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (gtks->gtk[i].status == GTK_STATUS_ACTIVE) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_gtk_status_is_live(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gtks->gtk[index].status == GTK_STATUS_FRESH || gtks->gtk[index].status == GTK_STATUS_ACTIVE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtk_status_new_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
|
||||
{
|
||||
if (index >= GTK_NUM || !gtks->gtk[index].set) {
|
||||
return;
|
||||
}
|
||||
|
||||
gtks->gtk[index].status = GTK_STATUS_NEW;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtks_hash_generate(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash)
|
||||
{
|
||||
memset(gtkhash, 0, GTK_ALL_HASHES_LEN);
|
||||
|
||||
uint8_t *gtk_hash_ptr = gtkhash;
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
|
||||
sec_prot_lib_gtkhash_generate(gtk, gtk_hash_ptr);
|
||||
}
|
||||
gtk_hash_ptr += GTK_HASH_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash)
|
||||
{
|
||||
uint8_t *gtk_hash_ptr = gtkhash;
|
||||
|
||||
gtk_mismatch_e mismatch = GTK_NO_MISMATCH;
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++, gtk_hash_ptr += 8) {
|
||||
// If hash is not set, stop using the key
|
||||
if (sec_prot_keys_gtk_hash_empty(gtk_hash_ptr)) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
uint32_t lifetime = sec_prot_keys_gtk_lifetime_get(gtks, i);
|
||||
if (lifetime > GTK_EXPIRE_MISMATCH_TIME) {
|
||||
tr_info("GTK mismatch %i expired time, lifetime: %"PRIu32"", i, lifetime);
|
||||
if (mismatch < GTK_LIFETIME_MISMATCH) {
|
||||
mismatch = GTK_LIFETIME_MISMATCH;
|
||||
}
|
||||
}
|
||||
sec_prot_keys_gtk_clear(gtks, i);
|
||||
}
|
||||
} else {
|
||||
// Check is hash matches to existing key
|
||||
uint8_t gtk_hash[8];
|
||||
uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
|
||||
if (!gtk) {
|
||||
// Hash set but GTK is not known, set mismatch
|
||||
tr_info("GTK mismatch: %i", i);
|
||||
if (mismatch < GTK_HASH_MISMATCH) {
|
||||
mismatch = GTK_HASH_MISMATCH;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
sec_prot_lib_gtkhash_generate(gtk, gtk_hash);
|
||||
|
||||
if (memcmp(gtk_hash, gtk_hash_ptr, 8) == 0) {
|
||||
// Key is fresh (or active, if old do not change state)
|
||||
sec_prot_keys_gtk_status_fresh_set(gtks, i);
|
||||
} else {
|
||||
// Hash does not match, set mismatch and delete key
|
||||
tr_info("GTK mismatch: %i", i);
|
||||
if (mismatch < GTK_HASH_MISMATCH) {
|
||||
mismatch = GTK_HASH_MISMATCH;
|
||||
}
|
||||
sec_prot_keys_gtk_clear(gtks, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mismatch;
|
||||
}
|
||||
|
||||
bool sec_prot_keys_gtk_hash_empty(uint8_t *gtkhash)
|
||||
{
|
||||
const uint8_t empty_hash[GTK_HASH_LEN] = {0};
|
||||
if (memcmp(gtkhash, empty_hash, GTK_HASH_LEN) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_install_order_last_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
int8_t install_order = -1;
|
||||
|
||||
// Gets the last key index
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
if (gtks->gtk[i].install_order > install_order) {
|
||||
install_order = gtks->gtk[i].install_order;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return install_order + 1;
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_install_order_last_index_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
int8_t install_order = -1;
|
||||
int8_t index = -1;
|
||||
|
||||
// Gets the last key index
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
if (gtks->gtk[i].install_order > install_order) {
|
||||
install_order = gtks->gtk[i].install_order;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
uint32_t sec_prot_keys_gtk_install_order_last_lifetime_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
uint32_t lifetime = 0;
|
||||
int8_t install_order = -1;
|
||||
|
||||
// Gets the last key index
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
if (gtks->gtk[i].install_order > install_order) {
|
||||
install_order = gtks->gtk[i].install_order;
|
||||
lifetime = gtks->gtk[i].lifetime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_install_order_first_index_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
// Gets the first key index
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
if (gtks->gtk[i].install_order == GTK_INSTALL_ORDER_FIRST) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_install_order_second_index_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
// Gets the first key index
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
if (gtks->gtk[i].install_order == GTK_INSTALL_ORDER_SECOND) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtk_install_order_update(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
int8_t ordered_indexes[4] = {-1, -1, -1, -1};
|
||||
|
||||
// Creates table of ordered indexes
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
ordered_indexes[gtks->gtk[i].install_order] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates indexes of the GTKs
|
||||
uint8_t new_install_order = 0;
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (ordered_indexes[i] >= 0) {
|
||||
gtks->gtk[ordered_indexes[i]].install_order = new_install_order++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int8_t sec_prot_keys_gtk_install_index_get(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
// Gets the index of the last key to be installed
|
||||
int8_t install_index = sec_prot_keys_gtk_install_order_last_index_get(gtks);
|
||||
if (install_index < 0) {
|
||||
install_index = 0;
|
||||
}
|
||||
|
||||
// Checks if there is free index, and available uses that for new GTK
|
||||
for (uint8_t ctr = 0, i = install_index; ctr < GTK_NUM; ctr++) {
|
||||
if (!sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
install_index = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
if (i >= GTK_NUM) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return install_index;
|
||||
}
|
||||
|
||||
uint8_t sec_prot_keys_gtk_count(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
|
@ -39,21 +39,36 @@
|
|||
|
||||
#define PMKID_LEN 16
|
||||
#define PTKID_LEN 16
|
||||
#define KEYID_LEN 16
|
||||
|
||||
#define GTK_DEFAULT_LIFETIME 60 * 60 * 24 * 30 // 30 days
|
||||
#define GTK_EXPIRE_MISMATCH_TIME 60 // Supplicant GTK expire time mismatch occurs if GTK expires before this time
|
||||
|
||||
#define GTK_STATUS_NEW 0 // New GTK, can transition to fresh
|
||||
#define GTK_STATUS_FRESH 1 // Fresh GTK, live based on hash, can transition to active
|
||||
#define GTK_STATUS_ACTIVE 2 // Active GTK, live based on hash, can transition to old
|
||||
#define GTK_STATUS_OLD 3 // Old GTK, not to be used for sending
|
||||
|
||||
#define GTK_INSTALL_ORDER_FIRST 0 // Install order runs from 0 to 3, where 0 is the GTK to be installed first
|
||||
#define GTK_INSTALL_ORDER_SECOND 1 // Install order runs from 0 to 3, where 1 is the GTK to be installed second
|
||||
|
||||
#define GTK_HASH_LEN 8
|
||||
#define GTK_ALL_HASHES_LEN GTK_HASH_LEN * GTK_NUM
|
||||
|
||||
#define PMK_LIFETIME_INSTALL 0xFFFFF
|
||||
#define PTK_LIFETIME_INSTALL 0xFFFFF
|
||||
|
||||
typedef struct {
|
||||
uint8_t key[GTK_LEN]; /**< Group Transient Key (128 bits) */
|
||||
uint32_t lifetime; /**< Lifetime is seconds */
|
||||
uint32_t lifetime; /**< GTK lifetime in seconds */
|
||||
unsigned status : 2; /**< Group Transient Key status */
|
||||
unsigned install_order : 2; /**< Order in which GTK keys are added */
|
||||
bool set: 1; /**< Group Transient Key set (valid value) */
|
||||
bool live: 1; /**< Group Transient Key live (as indicated by authenticator) */
|
||||
bool hash: 1; /**< Group Transient Key matches to hash */
|
||||
} gtk_key_t;
|
||||
|
||||
typedef struct {
|
||||
gtk_key_t gtk[GTK_NUM]; /**< 4 Group Transient Keys */
|
||||
int8_t gtk_set_index; /**< Group Transient Key to insert */
|
||||
bool updated; /**< Group Transient Keys has been updated */
|
||||
bool updated: 1; /**< Group Transient Keys has been updated */
|
||||
} sec_prot_gtk_keys_t;
|
||||
|
||||
// Security key data
|
||||
|
@ -61,15 +76,32 @@ typedef struct {
|
|||
uint64_t pmk_key_replay_cnt; /**< Pairwise Master Key replay counter */
|
||||
uint8_t pmk[PMK_LEN]; /**< Pairwise Master Key (256 bits) */
|
||||
uint8_t ptk[PTK_LEN]; /**< Pairwise Transient Key (384 bits) */
|
||||
uint8_t *ptk_eui_64; /**< Pointer to remote EUI-64 used to derive PTK or NULL */
|
||||
uint8_t ptk_eui_64[8]; /**< Remote EUI-64 used to derive PTK or NULL */
|
||||
sec_prot_gtk_keys_t *gtks; /**< Group Transient Keys */
|
||||
const sec_prot_certs_t *certs; /**< Certificates */
|
||||
uint32_t pmk_lifetime; /**< PMK lifetime in seconds */
|
||||
uint32_t ptk_lifetime; /**< PTK lifetime in seconds */
|
||||
uint8_t gtkl; /**< Remote GTKL information */
|
||||
int8_t gtk_set_index; /**< Index of GTK to set */
|
||||
bool pmk_set: 1; /**< Pairwise Master Key set */
|
||||
bool ptk_set: 1; /**< Pairwise Transient Key set */
|
||||
bool pmk_key_replay_cnt_set: 1; /**< Pairwise Master Key replay counter set */
|
||||
bool updated: 1; /**< Keys has been updated */
|
||||
bool ptk_eui_64_set: 1; /**< Remote EUI-64 used to derive PTK is set */
|
||||
bool pmk_mismatch: 1; /**< Remote PMK mismatch reported */
|
||||
bool ptk_mismatch: 1; /**< Remote PTK mismatch reported */
|
||||
} sec_prot_keys_t;
|
||||
|
||||
/*
|
||||
* GTK mismatch types, list is ordered according to priority of mismatch i.e. if there
|
||||
* are both hash and lifetime mismatch, hash has greater priority
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_NO_MISMATCH = 0,
|
||||
GTK_LIFETIME_MISMATCH,
|
||||
GTK_HASH_MISMATCH,
|
||||
} gtk_mismatch_e;
|
||||
|
||||
/**
|
||||
* sec_prot_keys_create allocates memory for security keys
|
||||
*
|
||||
|
@ -131,6 +163,14 @@ void sec_prot_keys_gtks_delete(sec_prot_gtk_keys_t *gtks);
|
|||
*/
|
||||
void sec_prot_keys_pmk_write(sec_prot_keys_t *sec_keys, uint8_t *pmk);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_pmk_delete deletes PMK
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_pmk_delete(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_pmk_get gets Pairwise Master Key
|
||||
*
|
||||
|
@ -168,6 +208,57 @@ void sec_prot_keys_pmk_replay_cnt_set(sec_prot_keys_t *sec_keys, uint64_t counte
|
|||
*/
|
||||
void sec_prot_keys_pmk_replay_cnt_increment(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_pmk_replay_cnt_compare compares received replay counter value to PMK replay counter
|
||||
*
|
||||
* \param received_counter received replay counter
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
* \return TRUE received replay counter is valid
|
||||
* \return FALSE received replay counter is not valid
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_pmk_replay_cnt_compare(uint64_t received_counter, sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_pmk_mismatch_set set PMK mismatch
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_pmk_mismatch_set(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_pmk_mismatch_reset reset PMK mismatch
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_pmk_mismatch_reset(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_pmk_mismatch_is_set check if PMK mismatch is set
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
* \return TRUE or FALSE
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_pmk_mismatch_is_set(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_pmk_lifetime_decrement decrements PMK lifetime
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
* \param default_lifetime default lifetime for PMK
|
||||
* \param seconds elapsed seconds
|
||||
*
|
||||
* \return true PMK expired and deleted both PMK and PTK
|
||||
* \return false PMK not expired
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_pmk_lifetime_decrement(sec_prot_keys_t *sec_keys, uint32_t default_lifetime, uint8_t seconds);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_write writes Pairwise Transient Key
|
||||
*
|
||||
|
@ -177,6 +268,14 @@ void sec_prot_keys_pmk_replay_cnt_increment(sec_prot_keys_t *sec_keys);
|
|||
*/
|
||||
void sec_prot_keys_ptk_write(sec_prot_keys_t *sec_keys, uint8_t *ptk);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_delete deletes PTK
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_ptk_delete(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_get gets Pairwise Transient Key
|
||||
*
|
||||
|
@ -188,13 +287,30 @@ void sec_prot_keys_ptk_write(sec_prot_keys_t *sec_keys, uint8_t *ptk);
|
|||
uint8_t *sec_prot_keys_ptk_get(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_eui_64_set sets PTK EUI-64 storage
|
||||
* sec_prot_keys_ptk_mismatch_set set PTK mismatch
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
* \param eui64 EUI-64 storage
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_ptk_eui_64_set(sec_prot_keys_t *sec_keys, uint8_t *eui_64);
|
||||
void sec_prot_keys_ptk_mismatch_set(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_mismatch_reset reset PTK mismatch
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_ptk_mismatch_reset(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_mismatch_is_set check if PTK mismatch is set
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
* \return TRUE or FALSE
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_ptk_mismatch_is_set(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_eui_64_write writes PTK EUI-64
|
||||
|
@ -203,7 +319,7 @@ void sec_prot_keys_ptk_eui_64_set(sec_prot_keys_t *sec_keys, uint8_t *eui_64);
|
|||
* \param eui64 EUI-64
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_ptk_eui_64_write(sec_prot_keys_t *sec_keys, uint8_t *eui_64);
|
||||
void sec_prot_keys_ptk_eui_64_write(sec_prot_keys_t *sec_keys, const uint8_t *eui_64);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_eui_64_get gets PTK EUI-64
|
||||
|
@ -215,6 +331,27 @@ void sec_prot_keys_ptk_eui_64_write(sec_prot_keys_t *sec_keys, uint8_t *eui_64);
|
|||
*/
|
||||
uint8_t *sec_prot_keys_ptk_eui_64_get(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_eui_64_delete deletes PTK EUI-64
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_ptk_eui_64_delete(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_ptk_lifetime_decrement decrements PTK lifetime
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
* \param default_lifetime default lifetime for PTK
|
||||
* \param seconds elapsed seconds
|
||||
*
|
||||
* \return true PTK expired and deleted
|
||||
* \return false PTK not expired
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_ptk_lifetime_decrement(sec_prot_keys_t *sec_keys, uint32_t default_lifetime, uint8_t seconds);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_are_updated returns security keys have been updated flag
|
||||
*
|
||||
|
@ -230,81 +367,111 @@ bool sec_prot_keys_are_updated(sec_prot_keys_t *sec_keys);
|
|||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_updated_reset(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtkl_get gets Group Transient Key liveness
|
||||
* sec_prot_keys_fresh_gtkl_get gets GTK liveness based on GTK status fields
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return bit field indicating GTK liveness
|
||||
*
|
||||
*/
|
||||
uint8_t sec_prot_keys_gtkl_get(sec_prot_gtk_keys_t *gtks);
|
||||
uint8_t sec_prot_keys_fresh_gtkl_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtkl_set sets Group Transient Key liveness
|
||||
* sec_prot_keys_gtkl_set sets GTK liveness storage
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param sec_keys security keys
|
||||
* \param gtkl bit field indicating GTK liveness
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtkl_set(sec_prot_gtk_keys_t *gtks, uint8_t gtkl);
|
||||
void sec_prot_keys_gtkl_set(sec_prot_keys_t *sec_keys, uint8_t gtkl);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_is_live checks if Group Transient Key is live
|
||||
* sec_prot_keys_gtkl_set checks whether GTK is live on GTK liveness storage
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param index GTK index
|
||||
* \param sec_keys security keys
|
||||
* \param index index of the GTK which liveness is returned
|
||||
*
|
||||
* \return TRUE GTK is live, FALSE GTK is not live
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_gtk_is_live(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
||||
bool sec_prot_keys_gtkl_gtk_is_live(sec_prot_keys_t *sec_keys, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtkl_gtk_live_set sets that GTK is live to GTK liveness storage
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
* \param index index of the GTK which is set live
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtkl_gtk_live_set(sec_prot_keys_t *sec_keys, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_insert_index_set sets index of GTK to be inserted
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param sec_keys security keys
|
||||
* \param index GTK index
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_insert_index_set(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
||||
int8_t sec_prot_keys_gtk_insert_index_set(sec_prot_keys_t *sec_keys, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_insert_index_get gets index of GTK to be inserted
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
* \return >= 0 GTK index
|
||||
* \return < 0 no GTK to be inserted
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_insert_index_get(sec_prot_gtk_keys_t *gtks);
|
||||
int8_t sec_prot_keys_gtk_insert_index_get(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_insert_index_clear clears the index of GTK to be inserted
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtk_insert_index_clear(sec_prot_gtk_keys_t *gtks);
|
||||
void sec_prot_keys_gtk_insert_index_clear(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtkl_from_gtk_insert_index_set sets inserted GTK as live to GTK liveness storage
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtkl_from_gtk_insert_index_set(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_insert_index_from_gtkl_get gets inserted GTK based on GTK liveness storage
|
||||
*
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
* \return >= 0 GTK index
|
||||
* \return < 0 no GTK to be inserted
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_insert_index_from_gtkl_get(sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_get_gtk_to_insert gets GTK that is marked to be inserted
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param sec_keys security keys
|
||||
* \param index index of the returned GTK
|
||||
*
|
||||
* \return GTK or NULL
|
||||
*
|
||||
*/
|
||||
uint8_t *sec_prot_keys_get_gtk_to_insert(sec_prot_gtk_keys_t *gtks, uint8_t *index);
|
||||
uint8_t *sec_prot_keys_get_gtk_to_insert(sec_prot_keys_t *sec_keys, uint8_t *index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_set sets Group Transient Key
|
||||
|
@ -312,12 +479,25 @@ uint8_t *sec_prot_keys_get_gtk_to_insert(sec_prot_gtk_keys_t *gtks, uint8_t *ind
|
|||
* \param gtks GTK keys
|
||||
* \param index index
|
||||
* \param gtk gtk value
|
||||
* \param lifetime GTK lifetime
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint8_t *gtk);
|
||||
int8_t sec_prot_keys_gtk_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint8_t *gtk, uint32_t lifetime);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_clear clears Group Transient Key
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param index index
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_clear(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_is_set checks if Group Transient Key is set
|
||||
|
@ -353,14 +533,16 @@ uint8_t *sec_prot_keys_gtk_get(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
|||
uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_lifetime_set sets GTK lifetime
|
||||
* sec_prot_keys_gtk_lifetime_decrement decrements GTK lifetime
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param index index
|
||||
* \param lifetime GTK lifetime
|
||||
* \param index index for GTK
|
||||
* \param seconds elapsed seconds
|
||||
*
|
||||
* \return new GTK lifetime
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtk_lifetime_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint32_t lifetime);
|
||||
uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint16_t seconds);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtks_are_updated returns GTKs have been updated flag
|
||||
|
@ -390,4 +572,163 @@ void sec_prot_keys_gtks_updated_set(sec_prot_gtk_keys_t *gtks);
|
|||
*/
|
||||
void sec_prot_keys_gtks_updated_reset(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_status_fresh_set sets GTK as status fresh (if GTK status new)
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param index index
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtk_status_fresh_set(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_status_fresh_set sets all GTK statuses fresh (if GTK status new)
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtk_status_all_fresh_set(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_status_active_set sets fresh GTK to active, and currently active as old
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param index index
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_status_active_set(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_status_active_get gets active GTK
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return >= 0 GTK index
|
||||
* \return < 0 no active GTK
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_status_active_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_status_is_live checks whether GTK is active
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param index index
|
||||
*
|
||||
* \return TRUE active, FALSE non active
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_gtk_status_is_live(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtks_hash_generate generate GTK hash based on all GTKs
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param gtk_hash GTK hash
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtks_hash_generate(sec_prot_gtk_keys_t *gtks, uint8_t *gtk_hash);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtks_hash_update update GTKs based on GTK hash
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
* \param gtk_hash GTK hash
|
||||
*
|
||||
* \return GTK mismatch type or no mismatch
|
||||
*
|
||||
*/
|
||||
gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_hash_empty checks if GTK hash field is empty
|
||||
*
|
||||
* \param gtk_hash GTK hash
|
||||
*
|
||||
* \return TRUE GTK hash is empty, FALSE GTK hash is set
|
||||
*
|
||||
*/
|
||||
bool sec_prot_keys_gtk_hash_empty(uint8_t *gtkhash);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_install_order_last_get gets install order of the last GTK to be installd
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return install order
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_install_order_last_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_install_order_last_get gets GTK that is to be installed last
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return GTK index
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_install_order_last_index_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_install_order_last_lifetime_get gets lifetime of the GTK that is to be installed last
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return lifetime
|
||||
*
|
||||
*/
|
||||
uint32_t sec_prot_keys_gtk_install_order_last_lifetime_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_install_order_first_index_get gets index of the GTK that is to be installed first
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return GTK index
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_install_order_first_index_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_install_order_second_index_get gets index of the GTK that is to be installed second first
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return GTK index
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_install_order_second_index_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_install_order_update updates install order (if GTKs are removed set the order back)
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtk_install_order_update(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_install_index_get gets a free index for GTK to be installed
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return GTK index
|
||||
*
|
||||
*/
|
||||
int8_t sec_prot_keys_gtk_install_index_get(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_count counts GTK keys
|
||||
*
|
||||
* \param gtks GTK keys
|
||||
*
|
||||
* \return count of keys, 0 for no keys
|
||||
*
|
||||
*/
|
||||
uint8_t sec_prot_keys_gtk_count(sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
#endif /* SEC_PROT_KEYS_H_ */
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "Service_Libs/ieee_802_11/ieee_802_11.h"
|
||||
#include "Service_Libs/hmac/hmac_sha1.h"
|
||||
#include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
|
@ -53,7 +54,7 @@ void sec_prot_init(sec_prot_common_t *data)
|
|||
|
||||
void sec_prot_timer_timeout_handle(sec_prot_t *prot, sec_prot_common_t *data, const trickle_params_t *trickle_params, uint16_t ticks)
|
||||
{
|
||||
if (data->trickle_running) {
|
||||
if (data->trickle_running && trickle_params) {
|
||||
bool running = trickle_running(&data->trickle_timer, trickle_params);
|
||||
|
||||
// Checks for trickle timer expiration */
|
||||
|
@ -108,9 +109,16 @@ void sec_prot_state_set(sec_prot_t *prot, sec_prot_common_t *data, uint8_t state
|
|||
return;
|
||||
|
||||
case SEC_STATE_FINISHED:
|
||||
// If not already on finished state
|
||||
if (data->state != SEC_STATE_FINISHED) {
|
||||
// Wait for timeout
|
||||
data->trickle_running = false;
|
||||
data->ticks = SEC_FINISHED_TIMEOUT;
|
||||
}
|
||||
data->trickle_running = false;
|
||||
|
||||
// Disables receiving of messages when state machine sets SEC_STATE_FINISHED
|
||||
prot->receive_disable(prot);
|
||||
|
||||
// Clear result
|
||||
sec_prot_result_set(data, SEC_RESULT_OK);
|
||||
break;
|
||||
|
@ -159,22 +167,10 @@ bool sec_prot_result_ok_check(sec_prot_common_t *data)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* IEEE 802.11 advises using sequential nonces, but should this be
|
||||
* randlib?
|
||||
*/
|
||||
void sec_prot_lib_nonce_generate(uint8_t *nonce)
|
||||
{
|
||||
// For now, use randlib
|
||||
// Use randlib
|
||||
randLIB_get_n_bytes_random(nonce, EAPOL_KEY_NONCE_LEN);
|
||||
|
||||
#if 0
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
if (++nonce[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -285,10 +281,11 @@ int8_t sec_prot_lib_pmkid_calc(const uint8_t *pmk, const uint8_t *auth_eui64, co
|
|||
ptr += EUI64_LEN;
|
||||
memcpy(ptr, supp_eui64, EUI64_LEN);
|
||||
|
||||
if (hmac_sha1_calc(pmk, PMK_LEN, data, data_len, pmkid) < 0) {
|
||||
if (hmac_sha1_calc(pmk, PMK_LEN, data, data_len, pmkid, PMKID_LEN) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_info("PMKID %s EUI-64 %s %s", trace_array(pmkid, PMKID_LEN), trace_array(auth_eui64, 8), trace_array(supp_eui64, 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -306,10 +303,11 @@ int8_t sec_prot_lib_ptkid_calc(const uint8_t *ptk, const uint8_t *auth_eui64, co
|
|||
ptr += EUI64_LEN;
|
||||
memcpy(ptr, supp_eui64, EUI64_LEN);
|
||||
|
||||
if (hmac_sha1_calc(ptk, PTK_LEN, data, data_len, ptkid) < 0) {
|
||||
if (hmac_sha1_calc(ptk, PTK_LEN, data, data_len, ptkid, PTKID_LEN) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_info("PTKID %s EUI-64 %s %s", trace_array(ptkid, PTKID_LEN), trace_array(auth_eui64, 8), trace_array(supp_eui64, 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -337,7 +335,7 @@ uint8_t *sec_prot_lib_message_build(uint8_t *ptk, uint8_t *kde, uint16_t kde_len
|
|||
|
||||
if (eapol_pdu->msg.key.key_information.key_mic) {
|
||||
uint8_t mic[EAPOL_KEY_MIC_LEN];
|
||||
if (hmac_sha1_calc(ptk, KCK_LEN, eapol_pdu_frame + header_size, eapol_pdu_size, mic) < 0) {
|
||||
if (hmac_sha1_calc(ptk, KCK_LEN, eapol_pdu_frame + header_size, eapol_pdu_size, mic, EAPOL_KEY_MIC_LEN) < 0) {
|
||||
ns_dyn_mem_free(eapol_pdu_frame);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -362,6 +360,7 @@ uint8_t *sec_prot_lib_message_handle(uint8_t *ptk, uint16_t *kde_len, eapol_pdu_
|
|||
if (eapol_pdu->msg.key.key_information.encrypted_key_data) {
|
||||
size_t output_len = eapol_pdu->msg.key.key_data_length;
|
||||
if (nist_aes_key_wrap(0, &ptk[KEK_INDEX], 128, key_data, key_data_len, kde, &output_len) < 0 || output_len != (size_t) key_data_len - 8) {
|
||||
tr_error("Decrypt failed");
|
||||
ns_dyn_mem_free(kde);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -373,42 +372,40 @@ uint8_t *sec_prot_lib_message_handle(uint8_t *ptk, uint16_t *kde_len, eapol_pdu_
|
|||
return kde;
|
||||
}
|
||||
|
||||
int8_t sec_prot_lib_gtk_read(uint8_t *kde, uint16_t kde_len, sec_prot_gtk_keys_t *gtks)
|
||||
int8_t sec_prot_lib_gtk_read(uint8_t *kde, uint16_t kde_len, sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
// If a valid new GTK value present, insert it
|
||||
int8_t gtk_set_index = -1;
|
||||
int8_t gtk_index = -1;
|
||||
|
||||
uint8_t key_id;
|
||||
uint8_t gtk[GTK_LEN];
|
||||
|
||||
if (kde_gtk_read(kde, kde_len, &key_id, gtk) >= 0) {
|
||||
// A new GTK value
|
||||
if (sec_prot_keys_gtk_set(gtks, key_id, gtk) >= 0) {
|
||||
gtk_set_index = (int8_t) key_id; // Insert
|
||||
uint32_t lifetime = 0;
|
||||
if (kde_lifetime_read(kde, kde_len, &lifetime) >= 0) {
|
||||
|
||||
}
|
||||
|
||||
uint32_t lifetime;
|
||||
if (kde_lifetime_read(kde, kde_len, &lifetime) >= 0) {
|
||||
sec_prot_keys_gtk_lifetime_set(gtks, key_id, lifetime);
|
||||
// A new GTK value
|
||||
if (sec_prot_keys_gtk_set(sec_keys->gtks, key_id, gtk, lifetime) >= 0) {
|
||||
gtk_index = (int8_t) key_id; // Insert
|
||||
}
|
||||
}
|
||||
uint8_t gtkl;
|
||||
if (kde_gtkl_read(kde, kde_len, >kl) >= 0) {
|
||||
sec_prot_keys_gtkl_set(gtks, gtkl);
|
||||
sec_prot_keys_gtkl_set(sec_keys, gtkl);
|
||||
} else {
|
||||
tr_error("No GTKL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Sanity checks
|
||||
if (gtk_set_index >= 0) {
|
||||
if (!sec_prot_keys_gtk_is_live(gtks, gtk_set_index)) {
|
||||
gtk_set_index = -1;
|
||||
if (gtk_index >= 0) {
|
||||
if (!sec_prot_keys_gtkl_gtk_is_live(sec_keys, gtk_index)) {
|
||||
tr_error("mismatch between GTK and GTKL");
|
||||
}
|
||||
}
|
||||
|
||||
if (gtk_set_index >= 0) {
|
||||
sec_prot_keys_gtk_insert_index_set(gtks, gtk_set_index);
|
||||
}
|
||||
tr_info("GTK recv index %i lifetime %"PRIu32"", gtk_index, sec_prot_keys_gtk_lifetime_get(sec_keys->gtks, gtk_index));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -421,45 +418,36 @@ int8_t sec_prot_lib_mic_validate(uint8_t *ptk, uint8_t *mic, uint8_t *pdu, uint8
|
|||
eapol_write_key_packet_mic(pdu, 0);
|
||||
|
||||
uint8_t calc_mic[EAPOL_KEY_MIC_LEN];
|
||||
if (hmac_sha1_calc(ptk, EAPOL_KEY_MIC_LEN, pdu, pdu_size, calc_mic) < 0) {
|
||||
if (hmac_sha1_calc(ptk, EAPOL_KEY_MIC_LEN, pdu, pdu_size, calc_mic, EAPOL_KEY_MIC_LEN) < 0) {
|
||||
tr_error("MIC invalid");
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(recv_mic, calc_mic, EAPOL_KEY_MIC_LEN) != 0) {
|
||||
tr_error("MIC invalid");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t sec_prot_lib_key_mask_get(eapol_pdu_t *eapol_pdu)
|
||||
{
|
||||
uint8_t key_mask = 0;
|
||||
|
||||
if (eapol_pdu->msg.key.key_information.install) {
|
||||
key_mask |= KEY_INFO_INSTALL;
|
||||
}
|
||||
if (eapol_pdu->msg.key.key_information.key_ack) {
|
||||
key_mask |= KEY_INFO_KEY_ACK;
|
||||
}
|
||||
if (eapol_pdu->msg.key.key_information.key_mic) {
|
||||
key_mask |= KEY_INFO_KEY_MIC;
|
||||
}
|
||||
if (eapol_pdu->msg.key.key_information.secured_key_frame) {
|
||||
key_mask |= KEY_INFO_SECURED_KEY_FRAME;
|
||||
}
|
||||
|
||||
return key_mask;
|
||||
}
|
||||
|
||||
int8_t sec_prot_lib_pmkid_generate(sec_prot_t *prot, uint8_t *pmkid, bool is_auth)
|
||||
{
|
||||
uint8_t local_eui64[8];
|
||||
uint8_t remote_eui64[8];
|
||||
prot->addr_get(prot, local_eui64, remote_eui64);
|
||||
uint8_t *pmk = sec_prot_keys_pmk_get(prot->sec_keys);
|
||||
if (!pmk) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t local_eui64[8];
|
||||
uint8_t remote_eui64[8];
|
||||
// Tries to get the EUI-64 that is validated by PTK procedure or bound to supplicant entry
|
||||
uint8_t *remote_eui64_ptr = sec_prot_keys_ptk_eui_64_get(prot->sec_keys);
|
||||
if (remote_eui64_ptr) {
|
||||
memcpy(remote_eui64, remote_eui64_ptr, 8);
|
||||
prot->addr_get(prot, local_eui64, NULL);
|
||||
} else {
|
||||
// If validated EUI-64 is not present, use the remote EUI-64
|
||||
prot->addr_get(prot, local_eui64, remote_eui64);
|
||||
}
|
||||
|
||||
if (is_auth) {
|
||||
return sec_prot_lib_pmkid_calc(pmk, local_eui64, remote_eui64, pmkid);
|
||||
} else {
|
||||
|
@ -470,12 +458,16 @@ int8_t sec_prot_lib_pmkid_generate(sec_prot_t *prot, uint8_t *pmkid, bool is_aut
|
|||
int8_t sec_prot_lib_ptkid_generate(sec_prot_t *prot, uint8_t *ptkid, bool is_auth)
|
||||
{
|
||||
uint8_t local_eui64[8];
|
||||
uint8_t remote_eui64[8];
|
||||
prot->addr_get(prot, local_eui64, remote_eui64);
|
||||
prot->addr_get(prot, local_eui64, NULL);
|
||||
uint8_t *ptk = sec_prot_keys_pmk_get(prot->sec_keys);
|
||||
if (!ptk) {
|
||||
return -1;
|
||||
}
|
||||
// Uses always the EUI-64 that is validated by PTK procedure or bound to supplicant entry
|
||||
uint8_t *remote_eui64 = sec_prot_keys_ptk_eui_64_get(prot->sec_keys);
|
||||
if (!remote_eui64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_auth) {
|
||||
return sec_prot_lib_ptkid_calc(ptk, local_eui64, remote_eui64, ptkid);
|
||||
|
@ -484,5 +476,46 @@ int8_t sec_prot_lib_ptkid_generate(sec_prot_t *prot, uint8_t *ptkid, bool is_aut
|
|||
}
|
||||
}
|
||||
|
||||
int8_t sec_prot_lib_gtkhash_generate(uint8_t *gtk, uint8_t *gtk_hash)
|
||||
{
|
||||
int8_t ret_val = 0;
|
||||
|
||||
mbedtls_sha256_context ctx;
|
||||
|
||||
mbedtls_sha256_init(&ctx);
|
||||
|
||||
if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
|
||||
ret_val = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mbedtls_sha256_update_ret(&ctx, gtk, 16) != 0) {
|
||||
ret_val = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
uint8_t output[32];
|
||||
|
||||
if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
|
||||
ret_val = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(gtk_hash, &output[24], 8);
|
||||
|
||||
error:
|
||||
mbedtls_sha256_free(&ctx);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
uint8_t *sec_prot_remote_eui_64_addr_get(sec_prot_t *prot)
|
||||
{
|
||||
if (prot->sec_keys && prot->sec_keys->ptk_eui_64_set) {
|
||||
return prot->sec_keys->ptk_eui_64;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue