/* * Copyright (c) 2022 Tomoyuki Sakurai * Copyright (c) 2023-2024 Simone Rossetto * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of * its contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #if !defined(__ESP_WIREGUARD__H__) #define __ESP_WIREGUARD__H__ #ifdef __cplusplus extern "C" { #endif #include "esp_wireguard_err.h" #include #include #include #define WG_KEY_LEN (32) #define WG_B64_KEY_LEN (4 * ((WG_KEY_LEN + 2) / 3)) typedef uint8_t wg_key_t[WG_KEY_LEN]; typedef struct { /* interface config */ wg_key_t private_key2; /**< private key generated by wg genkey. Required. */ uint16_t listen_port; /**< a 16-bit port for listening */ uint32_t fw_mark; /**< a 32-bit fwmark for outgoing packets */ /* peer config */ wg_key_t public_key2; /**< public key calculated by wg pubkey from a private key. Required. */ wg_key_t preshared_key2; /**< preshared key generated by wg genpsk. */ ip_addr_t address2; /**< a local IP address. */ ip_addr_t subnet; /**< a subnet mask of the local IP address. */ ip_addr_t netmask2; /**< the global subnet for the netif. */ const char* endpoint; /**< an endpoint IP address or hostname. */ ip_addr_t endpoint_ip; /**< endpoint IP address (internal use, resolved through dns query) */ uint16_t port; /**< a port number of remote endpoint. Default is 51820. */ uint16_t persistent_keepalive; /**< a seconds interval, between 1 and 65535 inclusive, of how often to send an authenticated empty packet to the peer for the purpose of keeping a stateful firewall or NAT mapping valid persistently. Set zero to disable the feature. Default is zero. */ } wireguard_config_t; typedef struct { wireguard_config_t* config; /**< a pointer to wireguard config */ struct netif* netif; /**< a pointer to configured netif */ } wireguard_ctx_t; /** * @brief Initialize WireGuard * * Call this function to initialize the context of WireGuard. * * Do not call this function multiple times. * * To connect to other peer, use `esp_wireguard_disconnect()`, and * `esp_wireguard_init()` with a new configuration. To reconnect to * the same peer just use `esp_wireguard_disconnect()` and then * `esp_wireguard_connect()`. * * @param config WireGuard configuration. * @param[out] ctx Context of WireGuard. * * @return * - ESP_OK: Successfully initilized WireGuard interface. * - ESP_ERR_INVALID_ARG: given argument is invalid. * - ESP_ERR_INVALID_STATE: hostname dns resolution cannot start * - ESP_FAIL: Other error. */ esp_err_t esp_wireguard_init(wireguard_config_t *config, wireguard_ctx_t *ctx); /** * @brief Create a WireGuard interface and start establishing the connection * to the peer. * * Call this function to start establishing the connection. Note that `ESP_OK` * does not mean the connection is established. To see if the connection is * established, or the peer is up, use `esp_wireguard_peer_is_up()`. * * Do not call this function multiple times. * * @param ctx Context of WireGuard. * @return * - ESP_OK on success. * - ESP_ERR_INVALID_ARG if input arguments are invalid * - ESP_ERR_RETRY dns query still ongoing for endpoint hostname resolution (retry connection) * - ESP_ERR_INVALID_IP if endpoint IP address is missing or invalid (dns query failed) * - ESP_FAIL on failure. */ esp_err_t esp_wireguard_connect(wireguard_ctx_t *ctx); /** * @brief Test if the peer is up. * @param ctx Context of WireGuard * @return * - ESP_OK on peer up. * - ESP_ERR_INVALID_ARG if ctx is NULL. * - ESP_FAIL on peer still down. */ esp_err_t esp_wireguard_peer_is_up(const wireguard_ctx_t *ctx); /** * @brief Get timestamp of the latest handshake (with seconds resolution since unix epoch) * @param ctx Context of WireGuard * @param result the output timestamp * @return * - ESP_OK on success * - ESP_FAIL if no handshake already completed * - ESP_ERR_INVALID_ARG if ctx is NULL * - ESP_ERR_INVALID_STATE if data inside ctx is not valid */ esp_err_t esp_wireguard_latest_handshake(const wireguard_ctx_t *ctx, time_t *result); /** * @brief Add new allowed IP/mask to the list of allowed ip/mask * @param ctx Context of WireGuard * @param allowed_ip The new IP to be allowed through tunnel * @param allowed_ip_mask The mask of the new IP * @return * - ESP_OK on success * - ESP_FAIL if the adding failed * - ESP_ERR_INVALID_ARG if ctx, allowed_ip or allowed_ip_mask are invalid or empty * - ESP_ERR_INVALID_STATE if data inside ctx is not valid */ esp_err_t esp_wireguard_add_allowed_ip(const wireguard_ctx_t *ctx, const ip_addr_t& allowed_ip, const ip_addr_t& allowed_ip_mask); /** * @brief Disconnect from the peer * * @param ctx Context of WireGuard. * @return * - ESP_OK on success. */ esp_err_t esp_wireguard_disconnect(wireguard_ctx_t *ctx); #ifdef __cplusplus } #endif #endif // vim: expandtab tabstop=4