mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-07-24 11:46:34 +00:00
Add wireguard library from https://github.com/ciniml/WireGuard-ESP32-Arduino
This commit is contained in:
parent
031c35d442
commit
45dd1ed438
1
lib/WireGuard-ESP32/.gitignore
vendored
Normal file
1
lib/WireGuard-ESP32/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
build.sh
|
28
lib/WireGuard-ESP32/LICENSE
Normal file
28
lib/WireGuard-ESP32/LICENSE
Normal file
@ -0,0 +1,28 @@
|
||||
Copyright (c) 2021 Kenta Ida (fuga@fugafuga.org)
|
||||
Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* 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.
|
||||
|
||||
Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
|
57
lib/WireGuard-ESP32/README.md
Normal file
57
lib/WireGuard-ESP32/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# WireGuard Implementation for ESP32 Arduino
|
||||
|
||||
This is an implementation of the [WireGuard®](https://www.wireguard.com/) for ESP32 Arduino.
|
||||
|
||||
Almost all of this code is based on the [WireGuard Implementation for lwIP](https://github.com/smartalock/wireguard-lwip), but some potion of the code is adjusted to build with ESP32 Arduino.
|
||||
|
||||
## How to use
|
||||
|
||||
1. Include `WireGuard-ESP32.h` at the early part of the sketch.
|
||||
|
||||
```c++
|
||||
#include <WireGuard-ESP32.h>
|
||||
```
|
||||
|
||||
2. Define the instance of the `WireGuard` class at module level.
|
||||
|
||||
```c++
|
||||
static WireGuard wg;
|
||||
```
|
||||
|
||||
3. Connect to WiFi AP by using `WiFi` class.
|
||||
|
||||
```c++
|
||||
WiFi.begin(ssid, password);
|
||||
while( !WiFi.isConnected() ) {
|
||||
delay(1000);
|
||||
}
|
||||
```
|
||||
|
||||
4. Sync the system time via NTP.
|
||||
|
||||
```c++
|
||||
configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com");
|
||||
```
|
||||
|
||||
5. Start the WireGuard interface.
|
||||
|
||||
```c++
|
||||
wg.begin(
|
||||
local_ip, // IP address of the local interface
|
||||
private_key, // Private key of the local interface
|
||||
endpoint_address, // Address of the endpoint peer.
|
||||
public_key, // Public key of the endpoint peer.
|
||||
endpoint_port); // Port pf the endpoint peer.
|
||||
```
|
||||
|
||||
You can see an example sketch `uptime_post.ino`, which connects SORACOM Arc WireGuard endpoint and post uptime to SORACOM Harvest via WireGuard connection.
|
||||
|
||||
## License
|
||||
|
||||
The original WireGuard implementation for lwIP is licensed under BSD 3 clause license so the code in this repository also licensed under the same license.
|
||||
|
||||
Original license is below:
|
||||
|
||||
The code is copyrighted under BSD 3 clause Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
|
||||
See LICENSE for details
|
10
lib/WireGuard-ESP32/library.properties
Normal file
10
lib/WireGuard-ESP32/library.properties
Normal file
@ -0,0 +1,10 @@
|
||||
name=WireGuard-ESP32
|
||||
version=0.1.5
|
||||
author=Kenta Ida
|
||||
maintainer=Kenta Ida <fuga@fugafuga.org>
|
||||
sentence=WireGuard implementation for Arduino ESP32
|
||||
paragraph=
|
||||
category=Communication
|
||||
url=https://github.com/ciniml/WireGuard-ESP32-Arduino
|
||||
includes=WireGuard-ESP32.h
|
||||
architectures=esp32,Inkplate
|
17
lib/WireGuard-ESP32/src/WireGuard-ESP32.h
Normal file
17
lib/WireGuard-ESP32/src/WireGuard-ESP32.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* WireGuard implementation for ESP32 Arduino by Kenta Ida (fuga@fugafuga.org)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#pragma once
|
||||
#include <IPAddress.h>
|
||||
|
||||
class WireGuard
|
||||
{
|
||||
private:
|
||||
bool _is_initialized = false;
|
||||
public:
|
||||
bool begin(const IPAddress& localIP, const IPAddress& Subnet, const IPAddress& Gateway, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort);
|
||||
bool begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort);
|
||||
void end();
|
||||
bool is_initialized() const { return this->_is_initialized; }
|
||||
};
|
147
lib/WireGuard-ESP32/src/WireGuard.cpp
Normal file
147
lib/WireGuard-ESP32/src/WireGuard.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* WireGuard implementation for ESP32 Arduino by Kenta Ida (fuga@fugafuga.org)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include "WireGuard-ESP32.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
extern "C" {
|
||||
#include "wireguardif.h"
|
||||
#include "wireguard-platform.h"
|
||||
}
|
||||
|
||||
// Wireguard instance
|
||||
static struct netif wg_netif_struct = {0};
|
||||
static struct netif *wg_netif = NULL;
|
||||
static struct netif *previous_default_netif = NULL;
|
||||
static uint8_t wireguard_peer_index = WIREGUARDIF_INVALID_INDEX;
|
||||
|
||||
#define TAG "[WireGuard] "
|
||||
|
||||
bool WireGuard::begin(const IPAddress& localIP, const IPAddress& Subnet, const IPAddress& Gateway, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort) {
|
||||
struct wireguardif_init_data wg;
|
||||
struct wireguardif_peer peer;
|
||||
ip_addr_t ipaddr = IPADDR4_INIT(static_cast<uint32_t>(localIP));
|
||||
ip_addr_t netmask = IPADDR4_INIT(static_cast<uint32_t>(Subnet));
|
||||
ip_addr_t gateway = IPADDR4_INIT(static_cast<uint32_t>(Gateway));
|
||||
|
||||
assert(privateKey != NULL);
|
||||
assert(remotePeerAddress != NULL);
|
||||
assert(remotePeerPublicKey != NULL);
|
||||
assert(remotePeerPort != 0);
|
||||
|
||||
// Setup the WireGuard device structure
|
||||
wg.private_key = privateKey;
|
||||
wg.listen_port = remotePeerPort;
|
||||
|
||||
wg.bind_netif = NULL;
|
||||
|
||||
// Initialise the first WireGuard peer structure
|
||||
wireguardif_peer_init(&peer);
|
||||
// If we know the endpoint's address can add here
|
||||
bool success_get_endpoint_ip = false;
|
||||
for(int retry = 0; retry < 5; retry++) {
|
||||
ip_addr_t endpoint_ip = IPADDR4_INIT_BYTES(0, 0, 0, 0);
|
||||
struct addrinfo *res = NULL;
|
||||
struct addrinfo hint;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
memset(&endpoint_ip, 0, sizeof(endpoint_ip));
|
||||
if( lwip_getaddrinfo(remotePeerAddress, NULL, &hint, &res) != 0 ) {
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
continue;
|
||||
}
|
||||
success_get_endpoint_ip = true;
|
||||
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&endpoint_ip), &addr4);
|
||||
lwip_freeaddrinfo(res);
|
||||
|
||||
peer.endpoint_ip = endpoint_ip;
|
||||
log_i(TAG "%s is %3d.%3d.%3d.%3d"
|
||||
, remotePeerAddress
|
||||
, (endpoint_ip.u_addr.ip4.addr >> 0) & 0xff
|
||||
, (endpoint_ip.u_addr.ip4.addr >> 8) & 0xff
|
||||
, (endpoint_ip.u_addr.ip4.addr >> 16) & 0xff
|
||||
, (endpoint_ip.u_addr.ip4.addr >> 24) & 0xff
|
||||
);
|
||||
break;
|
||||
}
|
||||
if( !success_get_endpoint_ip ) {
|
||||
log_e(TAG "failed to get endpoint ip.");
|
||||
return false;
|
||||
}
|
||||
// Register the new WireGuard network interface with lwIP
|
||||
wg_netif = netif_add(&wg_netif_struct, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gateway), &wg, &wireguardif_init, &ip_input);
|
||||
if( wg_netif == nullptr ) {
|
||||
log_e(TAG "failed to initialize WG netif.");
|
||||
return false;
|
||||
}
|
||||
// Mark the interface as administratively up, link up flag is set automatically when peer connects
|
||||
netif_set_up(wg_netif);
|
||||
|
||||
peer.public_key = remotePeerPublicKey;
|
||||
peer.preshared_key = NULL;
|
||||
// Allow all IPs through tunnel
|
||||
{
|
||||
ip_addr_t allowed_ip = IPADDR4_INIT_BYTES(0, 0, 0, 0);
|
||||
peer.allowed_ip = allowed_ip;
|
||||
ip_addr_t allowed_mask = IPADDR4_INIT_BYTES(0, 0, 0, 0);
|
||||
peer.allowed_mask = allowed_mask;
|
||||
}
|
||||
|
||||
peer.endport_port = remotePeerPort;
|
||||
|
||||
// Initialize the platform
|
||||
wireguard_platform_init();
|
||||
// Register the new WireGuard peer with the netwok interface
|
||||
wireguardif_add_peer(wg_netif, &peer, &wireguard_peer_index);
|
||||
if ((wireguard_peer_index != WIREGUARDIF_INVALID_INDEX) && !ip_addr_isany(&peer.endpoint_ip)) {
|
||||
// Start outbound connection to peer
|
||||
log_i(TAG "connecting wireguard...");
|
||||
wireguardif_connect(wg_netif, wireguard_peer_index);
|
||||
// Save the current default interface for restoring when shutting down the WG interface.
|
||||
previous_default_netif = netif_default;
|
||||
// Set default interface to WG device.
|
||||
netif_set_default(wg_netif);
|
||||
}
|
||||
|
||||
this->_is_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WireGuard::begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort) {
|
||||
// Maintain compatiblity with old begin
|
||||
auto subnet = IPAddress(255,255,255,255);
|
||||
auto gateway = IPAddress(0,0,0,0);
|
||||
return WireGuard::begin(localIP, subnet, gateway, privateKey, remotePeerAddress, remotePeerPublicKey, remotePeerPort);
|
||||
}
|
||||
|
||||
void WireGuard::end() {
|
||||
if( !this->_is_initialized ) return;
|
||||
|
||||
// Restore the default interface.
|
||||
netif_set_default(previous_default_netif);
|
||||
previous_default_netif = nullptr;
|
||||
// Disconnect the WG interface.
|
||||
wireguardif_disconnect(wg_netif, wireguard_peer_index);
|
||||
// Remove peer from the WG interface
|
||||
wireguardif_remove_peer(wg_netif, wireguard_peer_index);
|
||||
wireguard_peer_index = WIREGUARDIF_INVALID_INDEX;
|
||||
// Shutdown the wireguard interface.
|
||||
wireguardif_shutdown(wg_netif);
|
||||
// Remove the WG interface;
|
||||
netif_remove(wg_netif);
|
||||
wg_netif = nullptr;
|
||||
|
||||
this->_is_initialized = false;
|
||||
}
|
23
lib/WireGuard-ESP32/src/crypto.c
Normal file
23
lib/WireGuard-ESP32/src/crypto.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include "crypto.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void crypto_zero(void *dest, size_t len) {
|
||||
volatile uint8_t *p = (uint8_t *)dest;
|
||||
while (len--) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool crypto_equal(const void *a, const void *b, size_t size) {
|
||||
uint8_t neq = 0;
|
||||
while (size > 0) {
|
||||
neq |= *(uint8_t *)a ^ *(uint8_t *)b;
|
||||
a += 1;
|
||||
b += 1;
|
||||
size -= 1;
|
||||
}
|
||||
return (neq) ? false : true;
|
||||
}
|
102
lib/WireGuard-ESP32/src/crypto.h
Normal file
102
lib/WireGuard-ESP32/src/crypto.h
Normal file
@ -0,0 +1,102 @@
|
||||
#ifndef _CRYPTO_H_
|
||||
#define _CRYPTO_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// BLAKE2S IMPLEMENTATION
|
||||
#include "crypto/refc/blake2s.h"
|
||||
#define wireguard_blake2s_ctx blake2s_ctx
|
||||
#define wireguard_blake2s_init(ctx,outlen,key,keylen) blake2s_init(ctx,outlen,key,keylen)
|
||||
#define wireguard_blake2s_update(ctx,in,inlen) blake2s_update(ctx,in,inlen)
|
||||
#define wireguard_blake2s_final(ctx,out) blake2s_final(ctx,out)
|
||||
#define wireguard_blake2s(out,outlen,key,keylen,in,inlen) blake2s(out,outlen,key,keylen,in,inlen)
|
||||
|
||||
// X25519 IMPLEMENTATION
|
||||
#include "crypto/refc/x25519.h"
|
||||
#define wireguard_x25519(a,b,c) x25519(a,b,c,1)
|
||||
|
||||
// CHACHA20POLY1305 IMPLEMENTATION
|
||||
#include "crypto/refc/chacha20poly1305.h"
|
||||
#define wireguard_aead_encrypt(dst,src,srclen,ad,adlen,nonce,key) chacha20poly1305_encrypt(dst,src,srclen,ad,adlen,nonce,key)
|
||||
#define wireguard_aead_decrypt(dst,src,srclen,ad,adlen,nonce,key) chacha20poly1305_decrypt(dst,src,srclen,ad,adlen,nonce,key)
|
||||
#define wireguard_xaead_encrypt(dst,src,srclen,ad,adlen,nonce,key) xchacha20poly1305_encrypt(dst,src,srclen,ad,adlen,nonce,key)
|
||||
#define wireguard_xaead_decrypt(dst,src,srclen,ad,adlen,nonce,key) xchacha20poly1305_decrypt(dst,src,srclen,ad,adlen,nonce,key)
|
||||
|
||||
|
||||
// Endian / unaligned helper macros
|
||||
#define U8C(v) (v##U)
|
||||
#define U32C(v) (v##U)
|
||||
|
||||
#define U8V(v) ((uint8_t)(v) & U8C(0xFF))
|
||||
#define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF))
|
||||
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((uint32_t)((p)[0]) ) | \
|
||||
((uint32_t)((p)[1]) << 8) | \
|
||||
((uint32_t)((p)[2]) << 16) | \
|
||||
((uint32_t)((p)[3]) << 24))
|
||||
|
||||
#define U8TO64_LITTLE(p) \
|
||||
(((uint64_t)((p)[0]) ) | \
|
||||
((uint64_t)((p)[1]) << 8) | \
|
||||
((uint64_t)((p)[2]) << 16) | \
|
||||
((uint64_t)((p)[3]) << 24) | \
|
||||
((uint64_t)((p)[4]) << 32) | \
|
||||
((uint64_t)((p)[5]) << 40) | \
|
||||
((uint64_t)((p)[6]) << 48) | \
|
||||
((uint64_t)((p)[7]) << 56))
|
||||
|
||||
#define U16TO8_BIG(p, v) \
|
||||
do { \
|
||||
(p)[1] = U8V((v) ); \
|
||||
(p)[0] = U8V((v) >> 8); \
|
||||
} while (0)
|
||||
|
||||
#define U32TO8_LITTLE(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v) ); \
|
||||
(p)[1] = U8V((v) >> 8); \
|
||||
(p)[2] = U8V((v) >> 16); \
|
||||
(p)[3] = U8V((v) >> 24); \
|
||||
} while (0)
|
||||
|
||||
#define U32TO8_BIG(p, v) \
|
||||
do { \
|
||||
(p)[3] = U8V((v) ); \
|
||||
(p)[2] = U8V((v) >> 8); \
|
||||
(p)[1] = U8V((v) >> 16); \
|
||||
(p)[0] = U8V((v) >> 24); \
|
||||
} while (0)
|
||||
|
||||
#define U64TO8_LITTLE(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v) ); \
|
||||
(p)[1] = U8V((v) >> 8); \
|
||||
(p)[2] = U8V((v) >> 16); \
|
||||
(p)[3] = U8V((v) >> 24); \
|
||||
(p)[4] = U8V((v) >> 32); \
|
||||
(p)[5] = U8V((v) >> 40); \
|
||||
(p)[6] = U8V((v) >> 48); \
|
||||
(p)[7] = U8V((v) >> 56); \
|
||||
} while (0)
|
||||
|
||||
#define U64TO8_BIG(p, v) \
|
||||
do { \
|
||||
(p)[7] = U8V((v) ); \
|
||||
(p)[6] = U8V((v) >> 8); \
|
||||
(p)[5] = U8V((v) >> 16); \
|
||||
(p)[4] = U8V((v) >> 24); \
|
||||
(p)[3] = U8V((v) >> 32); \
|
||||
(p)[2] = U8V((v) >> 40); \
|
||||
(p)[1] = U8V((v) >> 48); \
|
||||
(p)[0] = U8V((v) >> 56); \
|
||||
} while (0)
|
||||
|
||||
|
||||
void crypto_zero(void *dest, size_t len);
|
||||
bool crypto_equal(const void *a, const void *b, size_t size);
|
||||
|
||||
#endif /* _CRYPTO_H_ */
|
||||
|
156
lib/WireGuard-ESP32/src/crypto/refc/blake2s.c
Normal file
156
lib/WireGuard-ESP32/src/crypto/refc/blake2s.c
Normal file
@ -0,0 +1,156 @@
|
||||
// Taken from RFC7693 - https://tools.ietf.org/html/rfc7693
|
||||
|
||||
#include "blake2s.h"
|
||||
#include "../../crypto.h"
|
||||
|
||||
// Cyclic right rotation.
|
||||
|
||||
#ifndef ROTR32
|
||||
#define ROTR32(x, y) (((x) >> (y)) ^ ((x) << (32 - (y))))
|
||||
#endif
|
||||
|
||||
// Mixing function G.
|
||||
#define B2S_G(a, b, c, d, x, y) { \
|
||||
v[a] = v[a] + v[b] + x; \
|
||||
v[d] = ROTR32(v[d] ^ v[a], 16); \
|
||||
v[c] = v[c] + v[d]; \
|
||||
v[b] = ROTR32(v[b] ^ v[c], 12); \
|
||||
v[a] = v[a] + v[b] + y; \
|
||||
v[d] = ROTR32(v[d] ^ v[a], 8); \
|
||||
v[c] = v[c] + v[d]; \
|
||||
v[b] = ROTR32(v[b] ^ v[c], 7); }
|
||||
|
||||
// Initialization Vector.
|
||||
static const uint32_t blake2s_iv[8] =
|
||||
{
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
|
||||
};
|
||||
|
||||
// Compression function. "last" flag indicates last block.
|
||||
static void blake2s_compress(blake2s_ctx *ctx, int last)
|
||||
{
|
||||
const uint8_t sigma[10][16] = {
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }
|
||||
};
|
||||
int i;
|
||||
uint32_t v[16], m[16];
|
||||
|
||||
for (i = 0; i < 8; i++) { // init work variables
|
||||
v[i] = ctx->h[i];
|
||||
v[i + 8] = blake2s_iv[i];
|
||||
}
|
||||
|
||||
v[12] ^= ctx->t[0]; // low 32 bits of offset
|
||||
v[13] ^= ctx->t[1]; // high 32 bits
|
||||
if (last) // last block flag set ?
|
||||
v[14] = ~v[14];
|
||||
for (i = 0; i < 16; i++) // get little-endian words
|
||||
m[i] = U8TO32_LITTLE(&ctx->b[4 * i]);
|
||||
|
||||
for (i = 0; i < 10; i++) { // ten rounds
|
||||
B2S_G( 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]);
|
||||
B2S_G( 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]);
|
||||
B2S_G( 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]);
|
||||
B2S_G( 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]);
|
||||
B2S_G( 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]);
|
||||
B2S_G( 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]);
|
||||
B2S_G( 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]);
|
||||
B2S_G( 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]);
|
||||
}
|
||||
|
||||
for( i = 0; i < 8; ++i )
|
||||
ctx->h[i] ^= v[i] ^ v[i + 8];
|
||||
}
|
||||
|
||||
// Initialize the hashing context "ctx" with optional key "key".
|
||||
// 1 <= outlen <= 32 gives the digest size in bytes.
|
||||
// Secret key (also <= 32 bytes) is optional (keylen = 0).
|
||||
int blake2s_init(blake2s_ctx *ctx, size_t outlen,
|
||||
const void *key, size_t keylen) // (keylen=0: no key)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (outlen == 0 || outlen > 32 || keylen > 32)
|
||||
return -1; // illegal parameters
|
||||
|
||||
for (i = 0; i < 8; i++) // state, "param block"
|
||||
ctx->h[i] = blake2s_iv[i];
|
||||
ctx->h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen;
|
||||
|
||||
ctx->t[0] = 0; // input count low word
|
||||
ctx->t[1] = 0; // input count high word
|
||||
ctx->c = 0; // pointer within buffer
|
||||
ctx->outlen = outlen;
|
||||
|
||||
for (i = keylen; i < 64; i++) // zero input block
|
||||
ctx->b[i] = 0;
|
||||
if (keylen > 0) {
|
||||
blake2s_update(ctx, key, keylen);
|
||||
ctx->c = 64; // at the end
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add "inlen" bytes from "in" into the hash.
|
||||
void blake2s_update(blake2s_ctx *ctx,
|
||||
const void *in, size_t inlen) // data bytes
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < inlen; i++) {
|
||||
if (ctx->c == 64) { // buffer full ?
|
||||
ctx->t[0] += ctx->c; // add counters
|
||||
if (ctx->t[0] < ctx->c) // carry overflow ?
|
||||
ctx->t[1]++; // high word
|
||||
blake2s_compress(ctx, 0); // compress (not last)
|
||||
ctx->c = 0; // counter to zero
|
||||
}
|
||||
ctx->b[ctx->c++] = ((const uint8_t *) in)[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the message digest (size given in init).
|
||||
// Result placed in "out".
|
||||
void blake2s_final(blake2s_ctx *ctx, void *out)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
ctx->t[0] += ctx->c; // mark last block offset
|
||||
if (ctx->t[0] < ctx->c) // carry overflow
|
||||
ctx->t[1]++; // high word
|
||||
|
||||
while (ctx->c < 64) // fill up with zeros
|
||||
ctx->b[ctx->c++] = 0;
|
||||
blake2s_compress(ctx, 1); // final block flag = 1
|
||||
|
||||
// little endian convert and store
|
||||
for (i = 0; i < ctx->outlen; i++) {
|
||||
((uint8_t *) out)[i] =
|
||||
(ctx->h[i >> 2] >> (8 * (i & 3))) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience function for all-in-one computation.
|
||||
int blake2s(void *out, size_t outlen,
|
||||
const void *key, size_t keylen,
|
||||
const void *in, size_t inlen)
|
||||
{
|
||||
blake2s_ctx ctx;
|
||||
if (blake2s_init(&ctx, outlen, key, keylen))
|
||||
return -1;
|
||||
blake2s_update(&ctx, in, inlen);
|
||||
blake2s_final(&ctx, out);
|
||||
|
||||
return 0;
|
||||
}
|
39
lib/WireGuard-ESP32/src/crypto/refc/blake2s.h
Normal file
39
lib/WireGuard-ESP32/src/crypto/refc/blake2s.h
Normal file
@ -0,0 +1,39 @@
|
||||
// Taken from RFC7693 - https://tools.ietf.org/html/rfc7693
|
||||
// BLAKE2s Hashing Context and API Prototypes
|
||||
#ifndef _BLAKE2S_H
|
||||
#define _BLAKE2S_H
|
||||
|
||||
#define BLAKE2S_BLOCK_SIZE 64
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// state context
|
||||
typedef struct {
|
||||
uint8_t b[64]; // input buffer
|
||||
uint32_t h[8]; // chained state
|
||||
uint32_t t[2]; // total number of bytes
|
||||
size_t c; // pointer for b[]
|
||||
size_t outlen; // digest size
|
||||
} blake2s_ctx;
|
||||
|
||||
// Initialize the hashing context "ctx" with optional key "key".
|
||||
// 1 <= outlen <= 32 gives the digest size in bytes.
|
||||
// Secret key (also <= 32 bytes) is optional (keylen = 0).
|
||||
int blake2s_init(blake2s_ctx *ctx, size_t outlen,
|
||||
const void *key, size_t keylen); // secret key
|
||||
|
||||
// Add "inlen" bytes from "in" into the hash.
|
||||
void blake2s_update(blake2s_ctx *ctx, // context
|
||||
const void *in, size_t inlen); // data to be hashed
|
||||
|
||||
// Generate the message digest (size given in init).
|
||||
// Result placed in "out".
|
||||
void blake2s_final(blake2s_ctx *ctx, void *out);
|
||||
|
||||
// All-in-one convenience function.
|
||||
int blake2s(void *out, size_t outlen, // return buffer for digest
|
||||
const void *key, size_t keylen, // optional secret key
|
||||
const void *in, size_t inlen); // data to be hashed
|
||||
|
||||
#endif
|
202
lib/WireGuard-ESP32/src/crypto/refc/chacha20.c
Normal file
202
lib/WireGuard-ESP32/src/crypto/refc/chacha20.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
*/
|
||||
|
||||
// RFC7539 implementation of ChaCha20 with modified nonce size for WireGuard
|
||||
// https://tools.ietf.org/html/rfc7539
|
||||
// Adapted from https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c by D. J. Bernstein (Public Domain)
|
||||
// HChaCha20 is described here: https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html
|
||||
|
||||
#include "chacha20.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "../../crypto.h"
|
||||
|
||||
// 2.3. The ChaCha20 Block Function
|
||||
// The first four words (0-3) are constants: 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
|
||||
static const uint32_t CHACHA20_CONSTANT_1 = 0x61707865;
|
||||
static const uint32_t CHACHA20_CONSTANT_2 = 0x3320646e;
|
||||
static const uint32_t CHACHA20_CONSTANT_3 = 0x79622d32;
|
||||
static const uint32_t CHACHA20_CONSTANT_4 = 0x6b206574;
|
||||
|
||||
#define ROTL32(v, n) (U32V((v) << (n)) | ((v) >> (32 - (n))))
|
||||
|
||||
#define PLUS(v,w) (U32V((v) + (w)))
|
||||
#define PLUSONE(v) (PLUS((v),1))
|
||||
|
||||
// 2.1. The ChaCha Quarter Round
|
||||
// 1. a += b; d ^= a; d <<<= 16;
|
||||
// 2. c += d; b ^= c; b <<<= 12;
|
||||
// 3. a += b; d ^= a; d <<<= 8;
|
||||
// 4. c += d; b ^= c; b <<<= 7;
|
||||
|
||||
#define QUARTERROUND(a, b, c, d) \
|
||||
a += b; d ^= a; d = ROTL32(d, 16); \
|
||||
c += d; b ^= c; b = ROTL32(b, 12); \
|
||||
a += b; d ^= a; d = ROTL32(d, 8); \
|
||||
c += d; b ^= c; b = ROTL32(b, 7)
|
||||
|
||||
static inline void INNER_BLOCK(uint32_t *block) {
|
||||
QUARTERROUND(block[0], block[4], block[ 8], block[12]); // column 0
|
||||
QUARTERROUND(block[1], block[5], block[ 9], block[13]); // column 1
|
||||
QUARTERROUND(block[2], block[6], block[10], block[14]); // column 2
|
||||
QUARTERROUND(block[3], block[7], block[11], block[15]); // column 3
|
||||
QUARTERROUND(block[0], block[5], block[10], block[15]); // diagonal 1
|
||||
QUARTERROUND(block[1], block[6], block[11], block[12]); // diagonal 2
|
||||
QUARTERROUND(block[2], block[7], block[ 8], block[13]); // diagonal 3
|
||||
QUARTERROUND(block[3], block[4], block[ 9], block[14]); // diagonal 4
|
||||
}
|
||||
|
||||
#define TWENTY_ROUNDS(x) ( \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x), \
|
||||
INNER_BLOCK(x) \
|
||||
)
|
||||
|
||||
// 2.3. The ChaCha20 Block Function
|
||||
// chacha20_block(key, counter, nonce):
|
||||
// state = constants | key | counter | nonce
|
||||
// working_state = state
|
||||
// for i=1 upto 10
|
||||
// inner_block(working_state)
|
||||
// end
|
||||
// state += working_state
|
||||
// return serialize(state)
|
||||
// end
|
||||
static void chacha20_block(struct chacha20_ctx *ctx, uint8_t *stream) {
|
||||
uint32_t working_state[16];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
working_state[i] = ctx->state[i];
|
||||
}
|
||||
|
||||
TWENTY_ROUNDS(working_state);
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
U32TO8_LITTLE(stream + (4 * i), PLUS(working_state[i], ctx->state[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void chacha20(struct chacha20_ctx *ctx, uint8_t *out, const uint8_t *in, uint32_t len) {
|
||||
uint8_t output[CHACHA20_BLOCK_SIZE];
|
||||
int i;
|
||||
|
||||
if (len) {
|
||||
for (;;) {
|
||||
chacha20_block(ctx, output);
|
||||
// Word 12 is a block counter
|
||||
ctx->state[12] = PLUSONE(ctx->state[12]);
|
||||
if (len <= 64) {
|
||||
for (i = 0;i < len;++i) {
|
||||
out[i] = in[i] ^ output[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (i = 0;i < 64;++i) {
|
||||
out[i] = in[i] ^ output[i];
|
||||
}
|
||||
len -= 64;
|
||||
out += 64;
|
||||
in += 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 2.3. The ChaCha20 Block Function
|
||||
// The first four words (0-3) are constants: 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
|
||||
// The next eight words (4-11) are taken from the 256-bit key by reading the bytes in little-endian order, in 4-byte chunks.
|
||||
// Word 12 is a block counter. Since each block is 64-byte, a 32-bit word is enough for 256 gigabytes of data.
|
||||
// Words 13-15 are a nonce, which should not be repeated for the same key.
|
||||
// For wireguard: "nonce being composed of 32 bits of zeros followed by the 64-bit little-endian value of counter." where counter comes from the Wireguard layer and is separate from the block counter in word 12
|
||||
void chacha20_init(struct chacha20_ctx *ctx, const uint8_t *key, const uint64_t nonce) {
|
||||
ctx->state[0] = CHACHA20_CONSTANT_1;
|
||||
ctx->state[1] = CHACHA20_CONSTANT_2;
|
||||
ctx->state[2] = CHACHA20_CONSTANT_3;
|
||||
ctx->state[3] = CHACHA20_CONSTANT_4;
|
||||
ctx->state[4] = U8TO32_LITTLE(key + 0);
|
||||
ctx->state[5] = U8TO32_LITTLE(key + 4);
|
||||
ctx->state[6] = U8TO32_LITTLE(key + 8);
|
||||
ctx->state[7] = U8TO32_LITTLE(key + 12);
|
||||
ctx->state[8] = U8TO32_LITTLE(key + 16);
|
||||
ctx->state[9] = U8TO32_LITTLE(key + 20);
|
||||
ctx->state[10] = U8TO32_LITTLE(key + 24);
|
||||
ctx->state[11] = U8TO32_LITTLE(key + 28);
|
||||
ctx->state[12] = 0;
|
||||
ctx->state[13] = 0;
|
||||
ctx->state[14] = nonce & 0xFFFFFFFF;
|
||||
ctx->state[15] = nonce >> 32;
|
||||
}
|
||||
|
||||
// 2.2. HChaCha20
|
||||
// HChaCha20 is initialized the same way as the ChaCha cipher, except that HChaCha20 uses a 128-bit nonce and has no counter.
|
||||
// After initialization, proceed through the ChaCha rounds as usual.
|
||||
// Once the 20 ChaCha rounds have been completed, the first 128 bits and last 128 bits of the ChaCha state (both little-endian) are concatenated, and this 256-bit subkey is returned.
|
||||
void hchacha20(uint8_t *out, const uint8_t *nonce, const uint8_t *key) {
|
||||
uint32_t state[16];
|
||||
state[0] = CHACHA20_CONSTANT_1;
|
||||
state[1] = CHACHA20_CONSTANT_2;
|
||||
state[2] = CHACHA20_CONSTANT_3;
|
||||
state[3] = CHACHA20_CONSTANT_4;
|
||||
state[4] = U8TO32_LITTLE(key + 0);
|
||||
state[5] = U8TO32_LITTLE(key + 4);
|
||||
state[6] = U8TO32_LITTLE(key + 8);
|
||||
state[7] = U8TO32_LITTLE(key + 12);
|
||||
state[8] = U8TO32_LITTLE(key + 16);
|
||||
state[9] = U8TO32_LITTLE(key + 20);
|
||||
state[10] = U8TO32_LITTLE(key + 24);
|
||||
state[11] = U8TO32_LITTLE(key + 28);
|
||||
state[12] = U8TO32_LITTLE(nonce + 0);
|
||||
state[13] = U8TO32_LITTLE(nonce + 4);
|
||||
state[14] = U8TO32_LITTLE(nonce + 8);
|
||||
state[15] = U8TO32_LITTLE(nonce + 12);
|
||||
|
||||
TWENTY_ROUNDS(state);
|
||||
|
||||
// Concatenate first/last 128 bits into 256bit output (as little endian)
|
||||
U32TO8_LITTLE(out + 0, state[0]);
|
||||
U32TO8_LITTLE(out + 4, state[1]);
|
||||
U32TO8_LITTLE(out + 8, state[2]);
|
||||
U32TO8_LITTLE(out + 12, state[3]);
|
||||
U32TO8_LITTLE(out + 16, state[12]);
|
||||
U32TO8_LITTLE(out + 20, state[13]);
|
||||
U32TO8_LITTLE(out + 24, state[14]);
|
||||
U32TO8_LITTLE(out + 28, state[15]);
|
||||
}
|
53
lib/WireGuard-ESP32/src/crypto/refc/chacha20.h
Normal file
53
lib/WireGuard-ESP32/src/crypto/refc/chacha20.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
*/
|
||||
|
||||
// RFC7539 implementation of ChaCha20 with modified nonce size for WireGuard
|
||||
// https://tools.ietf.org/html/rfc7539
|
||||
// Adapted from https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c by D. J. Bernstein (Public Domain)
|
||||
// HChaCha20 is described here: https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html
|
||||
#ifndef _CHACHA20_H_
|
||||
#define _CHACHA20_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define CHACHA20_BLOCK_SIZE (64)
|
||||
#define CHACHA20_KEY_SIZE (32)
|
||||
|
||||
struct chacha20_ctx {
|
||||
uint32_t state[16];
|
||||
};
|
||||
|
||||
void chacha20_init(struct chacha20_ctx *ctx, const uint8_t *key, const uint64_t nonce);
|
||||
void chacha20(struct chacha20_ctx *ctx, uint8_t *out, const uint8_t *in, uint32_t len);
|
||||
void hchacha20(uint8_t *out, const uint8_t *nonce, const uint8_t *key);
|
||||
|
||||
#endif /* _CHACHA20_H_ */
|
193
lib/WireGuard-ESP32/src/crypto/refc/chacha20poly1305.c
Normal file
193
lib/WireGuard-ESP32/src/crypto/refc/chacha20poly1305.c
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
*/
|
||||
|
||||
// AEAD_CHACHA20_POLY1305 as described in https://tools.ietf.org/html/rfc7539
|
||||
// AEAD_XChaCha20_Poly1305 as described in https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html
|
||||
#include "chacha20poly1305.h"
|
||||
#include "chacha20.h"
|
||||
#include "poly1305-donna.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "../../crypto.h"
|
||||
|
||||
#define POLY1305_KEY_SIZE 32
|
||||
#define POLY1305_MAC_SIZE 16
|
||||
|
||||
static const uint8_t zero[CHACHA20_BLOCK_SIZE] = { 0 };
|
||||
|
||||
// 2.6. Generating the Poly1305 Key Using ChaCha20
|
||||
static void generate_poly1305_key(struct poly1305_context *poly1305_state, struct chacha20_ctx *chacha20_state, const uint8_t *key, uint64_t nonce) {
|
||||
uint8_t block[POLY1305_KEY_SIZE] = {0};
|
||||
|
||||
// The method is to call the block function with the following parameters:
|
||||
// - The 256-bit session integrity key is used as the ChaCha20 key.
|
||||
// - The block counter is set to zero.
|
||||
// - The protocol will specify a 96-bit or 64-bit nonce
|
||||
chacha20_init(chacha20_state, key, nonce);
|
||||
|
||||
// We take the first 256 bits or the serialized state, and use those as the one-time Poly1305 key
|
||||
chacha20(chacha20_state, block, block, sizeof(block));
|
||||
|
||||
poly1305_init(poly1305_state, block);
|
||||
|
||||
crypto_zero(&block, sizeof(block));
|
||||
}
|
||||
|
||||
// 2.8. AEAD Construction (Encryption)
|
||||
void chacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key) {
|
||||
struct poly1305_context poly1305_state;
|
||||
struct chacha20_ctx chacha20_state;
|
||||
uint8_t block[8];
|
||||
size_t padded_len;
|
||||
|
||||
// First, a Poly1305 one-time key is generated from the 256-bit key and nonce using the procedure described in Section 2.6.
|
||||
generate_poly1305_key(&poly1305_state, &chacha20_state, key, nonce);
|
||||
|
||||
// Next, the ChaCha20 encryption function is called to encrypt the plaintext, using the same key and nonce, and with the initial counter set to 1.
|
||||
chacha20(&chacha20_state, dst, src, src_len);
|
||||
|
||||
// Finally, the Poly1305 function is called with the Poly1305 key calculated above, and a message constructed as a concatenation of the following:
|
||||
// - The AAD
|
||||
poly1305_update(&poly1305_state, ad, ad_len);
|
||||
// - padding1 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16
|
||||
padded_len = (ad_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes
|
||||
poly1305_update(&poly1305_state, zero, padded_len - ad_len);
|
||||
// - The ciphertext
|
||||
poly1305_update(&poly1305_state, dst, src_len);
|
||||
// - padding2 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16.
|
||||
padded_len = (src_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes
|
||||
poly1305_update(&poly1305_state, zero, padded_len - src_len);
|
||||
// - The length of the additional data in octets (as a 64-bit little-endian integer)
|
||||
U64TO8_LITTLE(block, (uint64_t)ad_len);
|
||||
poly1305_update(&poly1305_state, block, sizeof(block));
|
||||
// - The length of the ciphertext in octets (as a 64-bit little-endian integer).
|
||||
U64TO8_LITTLE(block, (uint64_t)src_len);
|
||||
poly1305_update(&poly1305_state, block, sizeof(block));
|
||||
|
||||
// The output from the AEAD is twofold:
|
||||
// - A ciphertext of the same length as the plaintext. (above, output of chacha20 into dst)
|
||||
// - A 128-bit tag, which is the output of the Poly1305 function. (append to dst)
|
||||
poly1305_finish(&poly1305_state, dst + src_len);
|
||||
|
||||
// Make sure we leave nothing sensitive on the stack
|
||||
crypto_zero(&chacha20_state, sizeof(chacha20_state));
|
||||
crypto_zero(&block, sizeof(block));
|
||||
}
|
||||
|
||||
// 2.8. AEAD Construction (Decryption)
|
||||
bool chacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key) {
|
||||
struct poly1305_context poly1305_state;
|
||||
struct chacha20_ctx chacha20_state;
|
||||
uint8_t block[8];
|
||||
uint8_t mac[POLY1305_MAC_SIZE];
|
||||
size_t padded_len;
|
||||
int dst_len;
|
||||
bool result = false;
|
||||
|
||||
// Decryption is similar [to encryption] with the following differences:
|
||||
// - The roles of ciphertext and plaintext are reversed, so the ChaCha20 encryption function is applied to the ciphertext, producing the plaintext.
|
||||
// - The Poly1305 function is still run on the AAD and the ciphertext, not the plaintext.
|
||||
// - The calculated tag is bitwise compared to the received tag. The message is authenticated if and only if the tags match.
|
||||
|
||||
if (src_len >= POLY1305_MAC_SIZE) {
|
||||
dst_len = src_len - POLY1305_MAC_SIZE;
|
||||
|
||||
// First, a Poly1305 one-time key is generated from the 256-bit key and nonce using the procedure described in Section 2.6.
|
||||
generate_poly1305_key(&poly1305_state, &chacha20_state, key, nonce);
|
||||
|
||||
// Calculate the MAC before attempting decryption
|
||||
|
||||
// the Poly1305 function is called with the Poly1305 key calculated above, and a message constructed as a concatenation of the following:
|
||||
// - The AAD
|
||||
poly1305_update(&poly1305_state, ad, ad_len);
|
||||
// - padding1 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16
|
||||
padded_len = (ad_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes
|
||||
poly1305_update(&poly1305_state, zero, padded_len - ad_len);
|
||||
// - The ciphertext (note the Poly1305 function is still run on the AAD and the ciphertext, not the plaintext)
|
||||
poly1305_update(&poly1305_state, src, dst_len);
|
||||
// - padding2 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16.
|
||||
padded_len = (dst_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes
|
||||
poly1305_update(&poly1305_state, zero, padded_len - dst_len);
|
||||
// - The length of the additional data in octets (as a 64-bit little-endian integer)
|
||||
U64TO8_LITTLE(block, (uint64_t)ad_len);
|
||||
poly1305_update(&poly1305_state, block, sizeof(block));
|
||||
// - The length of the ciphertext in octets (as a 64-bit little-endian integer).
|
||||
U64TO8_LITTLE(block, (uint64_t)dst_len);
|
||||
poly1305_update(&poly1305_state, block, sizeof(block));
|
||||
|
||||
// The output from the AEAD is twofold:
|
||||
// - A plaintext of the same length as the ciphertext. (below, output of chacha20 into dst)
|
||||
// - A 128-bit tag, which is the output of the Poly1305 function. (into mac for checking against passed mac)
|
||||
poly1305_finish(&poly1305_state, mac);
|
||||
|
||||
|
||||
if (crypto_equal(mac, src + dst_len, POLY1305_MAC_SIZE)) {
|
||||
// mac is correct - do the decryption
|
||||
// Next, the ChaCha20 encryption function is called to decrypt the ciphertext, using the same key and nonce, and with the initial counter set to 1.
|
||||
chacha20(&chacha20_state, dst, src, dst_len);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// AEAD_XChaCha20_Poly1305
|
||||
// XChaCha20-Poly1305 is a variant of the ChaCha20-Poly1305 AEAD construction as defined in [RFC7539] that uses a 192-bit nonce instead of a 96-bit nonce.
|
||||
// The algorithm for XChaCha20-Poly1305 is as follows:
|
||||
// 1. Calculate a subkey from the first 16 bytes of the nonce and the key, using HChaCha20 (Section 2.2).
|
||||
// 2. Use the subkey and remaining 8 bytes of the nonce (prefixed with 4 NUL bytes) with AEAD_CHACHA20_POLY1305 from [RFC7539] as normal. The definition for XChaCha20 is given in Section 2.3.
|
||||
void xchacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key) {
|
||||
uint8_t subkey[CHACHA20_KEY_SIZE];
|
||||
uint64_t new_nonce;
|
||||
|
||||
new_nonce = U8TO64_LITTLE(nonce + 16);
|
||||
|
||||
hchacha20(subkey, nonce, key);
|
||||
chacha20poly1305_encrypt(dst, src, src_len, ad, ad_len, new_nonce, subkey);
|
||||
|
||||
crypto_zero(subkey, sizeof(subkey));
|
||||
}
|
||||
|
||||
bool xchacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key) {
|
||||
uint8_t subkey[CHACHA20_KEY_SIZE];
|
||||
uint64_t new_nonce;
|
||||
bool result;
|
||||
|
||||
new_nonce = U8TO64_LITTLE(nonce + 16);
|
||||
|
||||
hchacha20(subkey, nonce, key);
|
||||
result = chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len, new_nonce, subkey);
|
||||
|
||||
crypto_zero(subkey, sizeof(subkey));
|
||||
return result;
|
||||
}
|
50
lib/WireGuard-ESP32/src/crypto/refc/chacha20poly1305.h
Normal file
50
lib/WireGuard-ESP32/src/crypto/refc/chacha20poly1305.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
*/
|
||||
|
||||
#ifndef _CHACHA20POLY1305_H_
|
||||
#define _CHACHA20POLY1305_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Aead(key, counter, plain text, auth text) ChaCha20Poly1305 AEAD, as specified in RFC7539 [17], with its nonce being composed of 32 bits of zeros followed by the 64-bit little-endian value of counter.
|
||||
// AEAD_CHACHA20_POLY1305 as described in https://tools.ietf.org/html/rfc7539
|
||||
void chacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key);
|
||||
bool chacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key);
|
||||
|
||||
// Xaead(key, nonce, plain text, auth text) XChaCha20Poly1305 AEAD, with a 24-byte random nonce, instantiated using HChaCha20 [6] and ChaCha20Poly1305.
|
||||
// AEAD_XChaCha20_Poly1305 as described in https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html
|
||||
void xchacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key);
|
||||
bool xchacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key);
|
||||
|
||||
#endif /* _CHACHA20POLY1305_H_ */
|
220
lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna-32.h
Normal file
220
lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna-32.h
Normal file
@ -0,0 +1,220 @@
|
||||
// Taken from https://github.com/floodyberry/poly1305-donna - public domain or MIT
|
||||
/*
|
||||
poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define POLY1305_NOINLINE __declspec(noinline)
|
||||
#elif defined(__GNUC__)
|
||||
#define POLY1305_NOINLINE __attribute__((noinline))
|
||||
#else
|
||||
#define POLY1305_NOINLINE
|
||||
#endif
|
||||
|
||||
#define poly1305_block_size 16
|
||||
|
||||
/* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */
|
||||
typedef struct poly1305_state_internal_t {
|
||||
unsigned long r[5];
|
||||
unsigned long h[5];
|
||||
unsigned long pad[4];
|
||||
size_t leftover;
|
||||
unsigned char buffer[poly1305_block_size];
|
||||
unsigned char final;
|
||||
} poly1305_state_internal_t;
|
||||
|
||||
/* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */
|
||||
static unsigned long
|
||||
U8TO32(const unsigned char *p) {
|
||||
return
|
||||
(((unsigned long)(p[0] & 0xff) ) |
|
||||
((unsigned long)(p[1] & 0xff) << 8) |
|
||||
((unsigned long)(p[2] & 0xff) << 16) |
|
||||
((unsigned long)(p[3] & 0xff) << 24));
|
||||
}
|
||||
|
||||
/* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */
|
||||
static void
|
||||
U32TO8(unsigned char *p, unsigned long v) {
|
||||
p[0] = (v ) & 0xff;
|
||||
p[1] = (v >> 8) & 0xff;
|
||||
p[2] = (v >> 16) & 0xff;
|
||||
p[3] = (v >> 24) & 0xff;
|
||||
}
|
||||
|
||||
void
|
||||
poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
|
||||
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||
st->r[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff;
|
||||
st->r[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03;
|
||||
st->r[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff;
|
||||
st->r[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff;
|
||||
st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
|
||||
|
||||
/* h = 0 */
|
||||
st->h[0] = 0;
|
||||
st->h[1] = 0;
|
||||
st->h[2] = 0;
|
||||
st->h[3] = 0;
|
||||
st->h[4] = 0;
|
||||
|
||||
/* save pad for later */
|
||||
st->pad[0] = U8TO32(&key[16]);
|
||||
st->pad[1] = U8TO32(&key[20]);
|
||||
st->pad[2] = U8TO32(&key[24]);
|
||||
st->pad[3] = U8TO32(&key[28]);
|
||||
|
||||
st->leftover = 0;
|
||||
st->final = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) {
|
||||
const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */
|
||||
unsigned long r0,r1,r2,r3,r4;
|
||||
unsigned long s1,s2,s3,s4;
|
||||
unsigned long h0,h1,h2,h3,h4;
|
||||
unsigned long long d0,d1,d2,d3,d4;
|
||||
unsigned long c;
|
||||
|
||||
r0 = st->r[0];
|
||||
r1 = st->r[1];
|
||||
r2 = st->r[2];
|
||||
r3 = st->r[3];
|
||||
r4 = st->r[4];
|
||||
|
||||
s1 = r1 * 5;
|
||||
s2 = r2 * 5;
|
||||
s3 = r3 * 5;
|
||||
s4 = r4 * 5;
|
||||
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
while (bytes >= poly1305_block_size) {
|
||||
/* h += m[i] */
|
||||
h0 += (U8TO32(m+ 0) ) & 0x3ffffff;
|
||||
h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
|
||||
h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
|
||||
h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
|
||||
h4 += (U8TO32(m+12) >> 8) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
|
||||
d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
|
||||
d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
|
||||
d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
|
||||
d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
|
||||
|
||||
/* (partial) h %= p */
|
||||
c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;
|
||||
d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;
|
||||
d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;
|
||||
d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;
|
||||
d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;
|
||||
h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
bytes -= poly1305_block_size;
|
||||
}
|
||||
|
||||
st->h[0] = h0;
|
||||
st->h[1] = h1;
|
||||
st->h[2] = h2;
|
||||
st->h[3] = h3;
|
||||
st->h[4] = h4;
|
||||
}
|
||||
|
||||
POLY1305_NOINLINE void
|
||||
poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
unsigned long h0,h1,h2,h3,h4,c;
|
||||
unsigned long g0,g1,g2,g3,g4;
|
||||
unsigned long long f;
|
||||
unsigned long mask;
|
||||
|
||||
/* process the remaining block */
|
||||
if (st->leftover) {
|
||||
size_t i = st->leftover;
|
||||
st->buffer[i++] = 1;
|
||||
for (; i < poly1305_block_size; i++)
|
||||
st->buffer[i] = 0;
|
||||
st->final = 1;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
}
|
||||
|
||||
/* fully carry h */
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
c = h1 >> 26; h1 = h1 & 0x3ffffff;
|
||||
h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
|
||||
h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
|
||||
h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
|
||||
g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
|
||||
g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
|
||||
g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
|
||||
g4 = h4 + c - (1UL << 26);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
|
||||
g0 &= mask;
|
||||
g1 &= mask;
|
||||
g2 &= mask;
|
||||
g3 &= mask;
|
||||
g4 &= mask;
|
||||
mask = ~mask;
|
||||
h0 = (h0 & mask) | g0;
|
||||
h1 = (h1 & mask) | g1;
|
||||
h2 = (h2 & mask) | g2;
|
||||
h3 = (h3 & mask) | g3;
|
||||
h4 = (h4 & mask) | g4;
|
||||
|
||||
/* h = h % (2^128) */
|
||||
h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
|
||||
h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
|
||||
h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
|
||||
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
|
||||
|
||||
/* mac = (h + pad) % (2^128) */
|
||||
f = (unsigned long long)h0 + st->pad[0] ; h0 = (unsigned long)f;
|
||||
f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f;
|
||||
f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f;
|
||||
f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f;
|
||||
|
||||
U32TO8(mac + 0, h0);
|
||||
U32TO8(mac + 4, h1);
|
||||
U32TO8(mac + 8, h2);
|
||||
U32TO8(mac + 12, h3);
|
||||
|
||||
/* zero out the state */
|
||||
st->h[0] = 0;
|
||||
st->h[1] = 0;
|
||||
st->h[2] = 0;
|
||||
st->h[3] = 0;
|
||||
st->h[4] = 0;
|
||||
st->r[0] = 0;
|
||||
st->r[1] = 0;
|
||||
st->r[2] = 0;
|
||||
st->r[3] = 0;
|
||||
st->r[4] = 0;
|
||||
st->pad[0] = 0;
|
||||
st->pad[1] = 0;
|
||||
st->pad[2] = 0;
|
||||
st->pad[3] = 0;
|
||||
}
|
||||
|
41
lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna.c
Normal file
41
lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna.c
Normal file
@ -0,0 +1,41 @@
|
||||
// Taken from https://github.com/floodyberry/poly1305-donna - public domain or MIT
|
||||
|
||||
#include "poly1305-donna.h"
|
||||
#include "poly1305-donna-32.h"
|
||||
|
||||
void
|
||||
poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) {
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
size_t i;
|
||||
|
||||
/* handle leftover */
|
||||
if (st->leftover) {
|
||||
size_t want = (poly1305_block_size - st->leftover);
|
||||
if (want > bytes)
|
||||
want = bytes;
|
||||
for (i = 0; i < want; i++)
|
||||
st->buffer[st->leftover + i] = m[i];
|
||||
bytes -= want;
|
||||
m += want;
|
||||
st->leftover += want;
|
||||
if (st->leftover < poly1305_block_size)
|
||||
return;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
st->leftover = 0;
|
||||
}
|
||||
|
||||
/* process full blocks */
|
||||
if (bytes >= poly1305_block_size) {
|
||||
size_t want = (bytes & ~(poly1305_block_size - 1));
|
||||
poly1305_blocks(st, m, want);
|
||||
m += want;
|
||||
bytes -= want;
|
||||
}
|
||||
|
||||
/* store leftover */
|
||||
if (bytes) {
|
||||
for (i = 0; i < bytes; i++)
|
||||
st->buffer[st->leftover + i] = m[i];
|
||||
st->leftover += bytes;
|
||||
}
|
||||
}
|
16
lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna.h
Normal file
16
lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna.h
Normal file
@ -0,0 +1,16 @@
|
||||
// Taken from https://github.com/floodyberry/poly1305-donna - public domain or MIT
|
||||
#ifndef POLY1305_DONNA_H
|
||||
#define POLY1305_DONNA_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct poly1305_context {
|
||||
size_t aligner;
|
||||
unsigned char opaque[136];
|
||||
} poly1305_context;
|
||||
|
||||
void poly1305_init(poly1305_context *ctx, const unsigned char key[32]);
|
||||
void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes);
|
||||
void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]);
|
||||
|
||||
#endif /* POLY1305_DONNA_H */
|
21
lib/WireGuard-ESP32/src/crypto/refc/x25519-license.txt
Normal file
21
lib/WireGuard-ESP32/src/crypto/refc/x25519-license.txt
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2016 Cryptography Research, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
448
lib/WireGuard-ESP32/src/crypto/refc/x25519.c
Normal file
448
lib/WireGuard-ESP32/src/crypto/refc/x25519.c
Normal file
@ -0,0 +1,448 @@
|
||||
// Taken from https://sourceforge.net/p/strobe (MIT Licence)
|
||||
/**
|
||||
* @cond internal
|
||||
* @file x25519.c
|
||||
* @copyright
|
||||
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
|
||||
* Released under the MIT License. See LICENSE.txt for license information.
|
||||
* @author Mike Hamburg
|
||||
* @brief Key exchange and signatures based on X25519.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "x25519.h"
|
||||
//#include "strobe.h"
|
||||
//#include "strobe_config.h"
|
||||
// STROBE header replacement
|
||||
#include <string.h>
|
||||
#define X25519_WBITS 32
|
||||
#define X25519_SUPPORT_SIGN 0
|
||||
#define X25519_MEMCPY_PARAMS 1
|
||||
#define X25519_USE_POWER_CHAIN 1
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
static inline uint32_t eswap_letoh_32(uint32_t w) { return w; }
|
||||
#else
|
||||
#error "Fix eswap() on non-little-endian machine"
|
||||
#endif
|
||||
|
||||
#if X25519_WBITS == 64
|
||||
typedef uint64_t limb_t;
|
||||
typedef __uint128_t dlimb_t;
|
||||
typedef __int128_t sdlimb_t;
|
||||
#define eswap_limb eswap_letoh_64
|
||||
#define LIMB(x) x##ull
|
||||
#elif X25519_WBITS == 32
|
||||
typedef uint32_t limb_t;
|
||||
typedef uint64_t dlimb_t;
|
||||
typedef int64_t sdlimb_t;
|
||||
#define eswap_limb eswap_letoh_32
|
||||
#define LIMB(x) (uint32_t)(x##ull),(uint32_t)((x##ull)>>32)
|
||||
#else
|
||||
#error "Need to know X25519_WBITS"
|
||||
#endif
|
||||
|
||||
#define NLIMBS (256/X25519_WBITS)
|
||||
typedef limb_t fe[NLIMBS];
|
||||
|
||||
#if X25519_SUPPORT_SIGN
|
||||
typedef limb_t scalar_t[NLIMBS];
|
||||
static const limb_t MONTGOMERY_FACTOR = (limb_t)0xd2b51da312547e1bull;
|
||||
static const scalar_t sc_p = {
|
||||
LIMB(0x5812631a5cf5d3ed), LIMB(0x14def9dea2f79cd6),
|
||||
LIMB(0x0000000000000000), LIMB(0x1000000000000000)
|
||||
}, sc_r2 = {
|
||||
LIMB(0xa40611e3449c0f01), LIMB(0xd00e1ba768859347),
|
||||
LIMB(0xceec73d217f5be65), LIMB(0x0399411b7c309a3d)
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline limb_t umaal(
|
||||
limb_t *carry, limb_t acc, limb_t mand, limb_t mier
|
||||
) {
|
||||
dlimb_t tmp = (dlimb_t) mand * mier + acc + *carry;
|
||||
*carry = tmp >> X25519_WBITS;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* These functions are implemented in terms of umaal on ARM */
|
||||
static inline limb_t adc(limb_t *carry, limb_t acc, limb_t mand) {
|
||||
dlimb_t total = (dlimb_t)*carry + acc + mand;
|
||||
*carry = total>>X25519_WBITS;
|
||||
return total;
|
||||
}
|
||||
|
||||
static inline limb_t adc0(limb_t *carry, limb_t acc) {
|
||||
dlimb_t total = (dlimb_t)*carry + acc;
|
||||
*carry = total>>X25519_WBITS;
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Precondition: carry is small.
|
||||
* Invariant: result of propagate is < 2^255 + 1 word
|
||||
* In particular, always less than 2p.
|
||||
* Also, output x >= min(x,19)
|
||||
*/
|
||||
static void propagate(fe x, limb_t over) {
|
||||
unsigned i;
|
||||
over = x[NLIMBS-1]>>(X25519_WBITS-1) | over<<1;
|
||||
x[NLIMBS-1] &= ~((limb_t)1<<(X25519_WBITS-1));
|
||||
|
||||
limb_t carry = over * 19;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
x[i] = adc0(&carry, x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void add(fe out, const fe a, const fe b) {
|
||||
unsigned i;
|
||||
limb_t carry = 0;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
out[i] = adc(&carry, a[i], b[i]);
|
||||
}
|
||||
propagate(out,carry);
|
||||
}
|
||||
|
||||
static void sub(fe out, const fe a, const fe b) {
|
||||
unsigned i;
|
||||
sdlimb_t carry = -38;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
out[i] = carry = carry + a[i] - b[i];
|
||||
carry >>= X25519_WBITS;
|
||||
}
|
||||
propagate(out,1+carry);
|
||||
}
|
||||
|
||||
static void __attribute__((unused))
|
||||
swapin(limb_t *x, const uint8_t *in) {
|
||||
memcpy(x,in,sizeof(fe));
|
||||
unsigned i;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
x[i] = eswap_limb(x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused))
|
||||
swapout(uint8_t *out, limb_t *x) {
|
||||
unsigned i;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
x[i] = eswap_limb(x[i]);
|
||||
}
|
||||
memcpy(out,x,sizeof(fe));
|
||||
}
|
||||
|
||||
static void mul(fe out, const fe a, const fe b, unsigned nb) {
|
||||
/* GCC at least produces pretty decent asm for this, so don't need to have dedicated asm. */
|
||||
limb_t accum[2*NLIMBS] = {0};
|
||||
unsigned i,j;
|
||||
|
||||
limb_t carry2;
|
||||
for (i=0; i<nb; i++) {
|
||||
carry2 = 0;
|
||||
limb_t mand = b[i];
|
||||
for (j=0; j<NLIMBS; j++) {
|
||||
accum[i+j] = umaal(&carry2, accum[i+j], mand, a[j]);
|
||||
}
|
||||
accum[i+j] = carry2;
|
||||
}
|
||||
|
||||
carry2 = 0;
|
||||
const limb_t mand = 38;
|
||||
for (j=0; j<NLIMBS; j++) {
|
||||
out[j] = umaal(&carry2, accum[j], mand, accum[j+NLIMBS]);
|
||||
}
|
||||
propagate(out,carry2);
|
||||
}
|
||||
|
||||
static void sqr(fe out, const fe a) { mul(out,a,a,NLIMBS); }
|
||||
static void mul1(fe out, const fe a) { mul(out,a,out,NLIMBS); }
|
||||
static void sqr1(fe a) { mul1(a,a); }
|
||||
|
||||
static void condswap(limb_t a[2*NLIMBS], limb_t b[2*NLIMBS], limb_t doswap) {
|
||||
unsigned i;
|
||||
for (i=0; i<2*NLIMBS; i++) {
|
||||
limb_t xor = (a[i]^b[i]) & doswap;
|
||||
a[i] ^= xor; b[i] ^= xor;
|
||||
}
|
||||
}
|
||||
|
||||
static limb_t canon(fe x) {
|
||||
/* Canonicalize a field element x, reducing it to the least residue
|
||||
* which is congruent to it mod 2^255-19.
|
||||
*
|
||||
* Precondition: x < 2^255 + 1 word
|
||||
*/
|
||||
|
||||
/* First, add 19. */
|
||||
unsigned i;
|
||||
limb_t carry0 = 19;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
x[i] = adc0(&carry0, x[i]);
|
||||
}
|
||||
propagate(x,carry0);
|
||||
|
||||
/* Here, 19 <= x2 < 2^255
|
||||
*
|
||||
* This is because we added 19, so before propagate it can't be less than 19.
|
||||
* After propagate, it still can't be less than 19, because if propagate does
|
||||
* anything it adds 19.
|
||||
*
|
||||
* We know that the high bit must be clear, because either the input was
|
||||
* ~ 2^255 + one word + 19 (in which case it propagates to at most 2 words)
|
||||
* or it was < 2^255.
|
||||
*
|
||||
* So now, if we subtract 19, we will get back to something in [0,2^255-19).
|
||||
*/
|
||||
sdlimb_t carry = -19;
|
||||
limb_t res = 0;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
res |= x[i] = carry += x[i];
|
||||
carry >>= X25519_WBITS;
|
||||
}
|
||||
return ((dlimb_t)res - 1) >> X25519_WBITS;
|
||||
}
|
||||
|
||||
static const limb_t a24[1]={121665};
|
||||
|
||||
static void ladder_part1(fe xs[5]) {
|
||||
limb_t *x2 = xs[0], *z2=xs[1],*x3=xs[2],*z3=xs[3],*t1=xs[4];
|
||||
add(t1,x2,z2); // t1 = A
|
||||
sub(z2,x2,z2); // z2 = B
|
||||
add(x2,x3,z3); // x2 = C
|
||||
sub(z3,x3,z3); // z3 = D
|
||||
mul1(z3,t1); // z3 = DA
|
||||
mul1(x2,z2); // x3 = BC
|
||||
add(x3,z3,x2); // x3 = DA+CB
|
||||
sub(z3,z3,x2); // z3 = DA-CB
|
||||
sqr1(t1); // t1 = AA
|
||||
sqr1(z2); // z2 = BB
|
||||
sub(x2,t1,z2); // x2 = E = AA-BB
|
||||
mul(z2,x2,a24,sizeof(a24)/sizeof(a24[0])); // z2 = E*a24
|
||||
add(z2,z2,t1); // z2 = E*a24 + AA
|
||||
}
|
||||
static void ladder_part2(fe xs[5], const fe x1) {
|
||||
limb_t *x2 = xs[0], *z2=xs[1],*x3=xs[2],*z3=xs[3],*t1=xs[4];
|
||||
sqr1(z3); // z3 = (DA-CB)^2
|
||||
mul1(z3,x1); // z3 = x1 * (DA-CB)^2
|
||||
sqr1(x3); // x3 = (DA+CB)^2
|
||||
mul1(z2,x2); // z2 = AA*(E*a24+AA)
|
||||
sub(x2,t1,x2); // x2 = BB again
|
||||
mul1(x2,t1); // x2 = AA*BB
|
||||
}
|
||||
|
||||
static void x25519_core(fe xs[5], const uint8_t scalar[X25519_BYTES], const uint8_t *x1, int clamp) {
|
||||
int i;
|
||||
#if X25519_MEMCPY_PARAMS
|
||||
fe x1i;
|
||||
swapin(x1i,x1);
|
||||
x1 = (const uint8_t *)x1;
|
||||
#endif
|
||||
limb_t swap = 0;
|
||||
limb_t *x2 = xs[0],*x3=xs[2],*z3=xs[3];
|
||||
memset(xs,0,4*sizeof(fe));
|
||||
x2[0] = z3[0] = 1;
|
||||
memcpy(x3,x1,sizeof(fe));
|
||||
|
||||
for (i=255; i>=0; i--) {
|
||||
uint8_t bytei = scalar[i/8];
|
||||
if (clamp) {
|
||||
if (i/8 == 0) {
|
||||
bytei &= ~7;
|
||||
} else if (i/8 == X25519_BYTES-1) {
|
||||
bytei &= 0x7F;
|
||||
bytei |= 0x40;
|
||||
}
|
||||
}
|
||||
limb_t doswap = -(limb_t)((bytei>>(i%8)) & 1);
|
||||
condswap(x2,x3,swap^doswap);
|
||||
swap = doswap;
|
||||
|
||||
ladder_part1(xs);
|
||||
ladder_part2(xs,(const limb_t *)x1);
|
||||
}
|
||||
condswap(x2,x3,swap);
|
||||
}
|
||||
|
||||
int x25519(uint8_t out[X25519_BYTES], const uint8_t scalar[X25519_BYTES], const uint8_t x1[X25519_BYTES], int clamp) {
|
||||
fe xs[5];
|
||||
x25519_core(xs,scalar,x1,clamp);
|
||||
|
||||
/* Precomputed inversion chain */
|
||||
limb_t *x2 = xs[0], *z2=xs[1], *z3=xs[3];
|
||||
int i;
|
||||
|
||||
limb_t *prev = z2;
|
||||
#if X25519_USE_POWER_CHAIN
|
||||
static const struct { uint8_t a,c,n; } steps[13] = {
|
||||
{2,1,1 },
|
||||
{2,1,1 },
|
||||
{4,2,3 },
|
||||
{2,4,6 },
|
||||
{3,1,1 },
|
||||
{3,2,12 },
|
||||
{4,3,25 },
|
||||
{2,3,25 },
|
||||
{2,4,50 },
|
||||
{3,2,125},
|
||||
{3,1,2 },
|
||||
{3,1,2 },
|
||||
{3,1,1 }
|
||||
};
|
||||
for (i=0; i<13; i++) {
|
||||
int j;
|
||||
limb_t *a = xs[steps[i].a];
|
||||
for (j=steps[i].n; j>0; j--) {
|
||||
sqr(a, prev);
|
||||
prev = a;
|
||||
}
|
||||
mul1(a,xs[steps[i].c]);
|
||||
}
|
||||
#else
|
||||
/* Raise to the p-2 = 0x7f..ffeb */
|
||||
for (i=253; i>=0; i--) {
|
||||
sqr(z3,prev);
|
||||
prev = z3;
|
||||
if (i>=8 || (0xeb>>i & 1)) {
|
||||
mul1(z3,z2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Here prev = z3 */
|
||||
/* x2 /= z2 */
|
||||
#if X25519_MEMCPY_PARAMS
|
||||
mul1(x2,z3);
|
||||
int ret = canon(x2);
|
||||
swapout(out,x2);
|
||||
#else
|
||||
mul((limb_t *)out, x2, z3, NLIMBS);
|
||||
int ret = canon((limb_t*)out);
|
||||
#endif
|
||||
if (clamp) return ret;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
const uint8_t X25519_BASE_POINT[X25519_BYTES] = {9};
|
||||
|
||||
#if X25519_SUPPORT_VERIFY
|
||||
static limb_t x25519_verify_core(
|
||||
fe xs[5],
|
||||
const limb_t *other1,
|
||||
const uint8_t other2[X25519_BYTES]
|
||||
) {
|
||||
limb_t *z2=xs[1],*x3=xs[2],*z3=xs[3];
|
||||
#if X25519_MEMCPY_PARAMS
|
||||
fe xo2;
|
||||
swapin(xo2,other2);
|
||||
#else
|
||||
const limb_t *xo2 = (const limb_t *)other2;
|
||||
#endif
|
||||
|
||||
memcpy(x3, other1, 2*sizeof(fe));
|
||||
|
||||
ladder_part1(xs);
|
||||
|
||||
/* Here z2 = t2^2 */
|
||||
mul1(z2,other1);
|
||||
mul1(z2,other1+NLIMBS);
|
||||
mul1(z2,xo2);
|
||||
const limb_t sixteen = 16;
|
||||
mul (z2,z2,&sixteen,1);
|
||||
|
||||
mul1(z3,xo2);
|
||||
sub(z3,z3,x3);
|
||||
sqr1(z3);
|
||||
|
||||
/* check equality */
|
||||
sub(z3,z3,z2);
|
||||
|
||||
/* If canon(z2) then both sides are zero.
|
||||
* If canon(z3) then the two sides are equal.
|
||||
*
|
||||
* Reject sigs where both sides are zero, because
|
||||
* that can happen if an input causes the ladder to
|
||||
* return 0/0.
|
||||
*/
|
||||
return canon(z2) | ~canon(z3);
|
||||
}
|
||||
|
||||
int x25519_verify_p2 (
|
||||
const uint8_t response[X25519_BYTES],
|
||||
const uint8_t challenge[X25519_BYTES],
|
||||
const uint8_t eph[X25519_BYTES],
|
||||
const uint8_t pub[X25519_BYTES]
|
||||
) {
|
||||
fe xs[7];
|
||||
x25519_core(&xs[0],challenge,pub,0);
|
||||
x25519_core(&xs[2],response,X25519_BASE_POINT,0);
|
||||
return x25519_verify_core(&xs[2],xs[0],eph);
|
||||
}
|
||||
#endif // X25519_SUPPORT_VERIFY
|
||||
|
||||
#if X25519_SUPPORT_SIGN
|
||||
static void sc_montmul (
|
||||
scalar_t out,
|
||||
const scalar_t a,
|
||||
const scalar_t b
|
||||
) {
|
||||
/**
|
||||
* OK, so carry bounding. We're using a high carry, so that the
|
||||
* inputs don't have to be reduced.
|
||||
*
|
||||
* First montmul: output < (M^2 + Mp)/M = M+p, subtract p, < M. This gets rid of high carry.
|
||||
* Second montmul, by r^2 mod p < p: output < (Mp + Mp)/M = 2p, subtract p, < p, done.
|
||||
*/
|
||||
unsigned i,j;
|
||||
limb_t hic = 0;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
limb_t carry=0, carry2=0, mand = a[i], mand2 = MONTGOMERY_FACTOR;
|
||||
|
||||
for (j=0; j<NLIMBS; j++) {
|
||||
limb_t acc = out[j];
|
||||
acc = umaal(&carry, acc, mand, b[j]);
|
||||
if (j==0) mand2 *= acc;
|
||||
acc = umaal(&carry2, acc, mand2, sc_p[j]);
|
||||
if (j>0) out[j-1] = acc;
|
||||
}
|
||||
|
||||
/* Add two carry registers and high carry */
|
||||
out[NLIMBS-1] = adc(&hic, carry, carry2);
|
||||
}
|
||||
|
||||
/* Reduce */
|
||||
sdlimb_t scarry = 0;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
out[i] = scarry = scarry + out[i] - sc_p[i];
|
||||
scarry >>= X25519_WBITS;
|
||||
}
|
||||
limb_t need_add = -(scarry + hic);
|
||||
|
||||
limb_t carry = 0;
|
||||
for (i=0; i<NLIMBS; i++) {
|
||||
out[i] = umaal(&carry, out[i], need_add, sc_p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void x25519_sign_p2 (
|
||||
uint8_t response[X25519_BYTES],
|
||||
const uint8_t challenge[X25519_BYTES],
|
||||
const uint8_t eph_secret[X25519_BYTES],
|
||||
const uint8_t secret[X25519_BYTES]
|
||||
) {
|
||||
/* FUTURE memory/code size: just make eph_secret non-const? */
|
||||
scalar_t scalar1;
|
||||
swapin(scalar1,eph_secret);
|
||||
|
||||
#if X25519_MEMCPY_PARAMS
|
||||
scalar_t scalar2, scalar3;
|
||||
swapin(scalar2,secret);
|
||||
swapin(scalar3,challenge);
|
||||
sc_montmul(scalar1,scalar2,scalar3);
|
||||
memset(scalar2,0,sizeof(scalar2));
|
||||
sc_montmul(scalar2,scalar1,sc_r2);
|
||||
swapout(response,scalar2);
|
||||
#else
|
||||
sc_montmul(scalar1,(const limb_t *)secret,(const limb_t *)challenge);
|
||||
memset(response,0,X25519_BYTES);
|
||||
sc_montmul((limb_t *)response,scalar1,sc_r2);
|
||||
#endif
|
||||
}
|
||||
#endif // X25519_SUPPORT_SIGN
|
129
lib/WireGuard-ESP32/src/crypto/refc/x25519.h
Normal file
129
lib/WireGuard-ESP32/src/crypto/refc/x25519.h
Normal file
@ -0,0 +1,129 @@
|
||||
// Taken from https://sourceforge.net/p/strobe (MIT Licence)
|
||||
/**
|
||||
* @file x25519.h
|
||||
* @copyright
|
||||
* Copyright (c) 2016 Cryptography Research, Inc. \n
|
||||
* Released under the MIT License. See LICENSE.txt for license information.
|
||||
* @author Mike Hamburg
|
||||
* @brief X25519 key exchange and signatures.
|
||||
*/
|
||||
|
||||
#ifndef __X25519_H__
|
||||
#define __X25519_H__
|
||||
|
||||
#define X25519_BYTES (256/8)
|
||||
|
||||
/* The base point (9) */
|
||||
extern const unsigned char X25519_BASE_POINT[X25519_BYTES];
|
||||
|
||||
/** Number of bytes in an EC public key */
|
||||
#define EC_PUBLIC_BYTES 32
|
||||
|
||||
/** Number of bytes in an EC private key */
|
||||
#define EC_PRIVATE_BYTES 32
|
||||
|
||||
/**
|
||||
* Number of bytes in a Schnorr challenge.
|
||||
* Could be set to 16 in a pinch. (FUTURE?)
|
||||
*/
|
||||
#define EC_CHALLENGE_BYTES 32
|
||||
|
||||
/** Enough bytes to get a uniform sample mod #E. For eg a Brainpool
|
||||
* curve this would need to be more than for a private key, but due
|
||||
* to the special prime used by Curve25519, the same size is enough.
|
||||
*/
|
||||
#define EC_UNIFORM_BYTES 32
|
||||
|
||||
/* x25519 scalar multiplication. Sets out to scalar*base.
|
||||
*
|
||||
* If clamp is set (and supported by X25519_INTEROP_SUPPORT_CLAMP)
|
||||
* then the scalar will be "clamped" like a Curve25519 secret key.
|
||||
* This adds almost no security, but permits interop with other x25519
|
||||
* implementations without manually clamping the keys.
|
||||
*
|
||||
* Per RFC 7748, this function returns failure (-1) if the output
|
||||
* is zero and clamp is set. This indicates "non-contributory behavior",
|
||||
* meaning that one party might steer the key so that the other party's
|
||||
* contribution doesn't matter, or contributes only a little entropy.
|
||||
*
|
||||
* WARNING: however, this function differs from RFC 7748 in another way:
|
||||
* it pays attention to the high bit base[EC_PUBLIC_BYTES-1] & 0x80, but
|
||||
* RFC 7748 says to ignore this bit. For compatibility with RFC 7748,
|
||||
* you must also clear this bit by running base[EC_PUBLIC_BYTES-1] &= 0x7F.
|
||||
* This library won't clear it for you because it takes the base point as
|
||||
* const, and (depending on build flags) dosen't copy it.
|
||||
*
|
||||
* If clamp==0, or if X25519_INTEROP_SUPPORT_CLAMP==0, then this function
|
||||
* always returns 0.
|
||||
*/
|
||||
int x25519 (
|
||||
unsigned char out[EC_PUBLIC_BYTES],
|
||||
const unsigned char scalar[EC_PRIVATE_BYTES],
|
||||
const unsigned char base[EC_PUBLIC_BYTES],
|
||||
int clamp
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*
|
||||
* Per RFC 7748, this function returns failure if the output
|
||||
* is zero and clamp is set. This usually doesn't matter for
|
||||
* base scalarmuls.
|
||||
*
|
||||
* If clamp==0, or if X25519_INTEROP_SUPPORT_CLAMP==0, then this function
|
||||
* always returns 0.
|
||||
*
|
||||
* Same as x255(out,scalar,X255_BASE_POINT), except that
|
||||
* other implementations may optimize it.
|
||||
*/
|
||||
static inline int x25519_base (
|
||||
unsigned char out[EC_PUBLIC_BYTES],
|
||||
const unsigned char scalar[EC_PRIVATE_BYTES],
|
||||
int clamp
|
||||
) {
|
||||
return x25519(out,scalar,X25519_BASE_POINT,clamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* As x25519_base, but with a scalar that's EC_UNIFORM_BYTES long,
|
||||
* and clamp always 0 (and thus, no return value).
|
||||
*
|
||||
* This is used for signing. Implementors must replace it for
|
||||
* curves that require more bytes for uniformity (Brainpool).
|
||||
*/
|
||||
static inline void x25519_base_uniform (
|
||||
unsigned char out[EC_PUBLIC_BYTES],
|
||||
const unsigned char scalar[EC_UNIFORM_BYTES]
|
||||
) {
|
||||
(void)x25519_base(out,scalar,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* STROBE-compatible Schnorr signatures using curve25519 (not ed25519)
|
||||
*
|
||||
* The user will call x25519_base_uniform(eph,eph_secret) to schedule
|
||||
* a random ephemeral secret key. They then call a Schnorr oracle to
|
||||
* get a challenge, and compute the response using this function.
|
||||
*/
|
||||
void x25519_sign_p2 (
|
||||
unsigned char response[EC_PRIVATE_BYTES],
|
||||
const unsigned char challenge[EC_CHALLENGE_BYTES],
|
||||
const unsigned char eph_secret[EC_UNIFORM_BYTES],
|
||||
const unsigned char secret[EC_PRIVATE_BYTES]
|
||||
);
|
||||
|
||||
/**
|
||||
* STROBE-compatible signature verification using curve25519 (not ed25519).
|
||||
* This function is the public equivalent x25519_sign_p2, taking the long-term
|
||||
* and ephemeral public keys instead of secret ones.
|
||||
*
|
||||
* Returns -1 on failure and 0 on success.
|
||||
*/
|
||||
int x25519_verify_p2 (
|
||||
const unsigned char response[X25519_BYTES],
|
||||
const unsigned char challenge[X25519_BYTES],
|
||||
const unsigned char eph[X25519_BYTES],
|
||||
const unsigned char pub[X25519_BYTES]
|
||||
);
|
||||
|
||||
#endif /* __X25519_H__ */
|
68
lib/WireGuard-ESP32/src/wireguard-platform.c
Normal file
68
lib/WireGuard-ESP32/src/wireguard-platform.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* WireGuard implementation for ESP32 Arduino by Kenta Ida (fuga@fugafuga.org)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "wireguard-platform.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "crypto.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
static struct mbedtls_ctr_drbg_context random_context;
|
||||
static struct mbedtls_entropy_context entropy_context;
|
||||
static bool is_platform_initialized = false;
|
||||
|
||||
static int entropy_hw_random_source( void *data, unsigned char *output, size_t len, size_t *olen ) {
|
||||
esp_fill_random(output, len);
|
||||
*olen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wireguard_platform_init() {
|
||||
if( is_platform_initialized ) return;
|
||||
|
||||
mbedtls_entropy_init(&entropy_context);
|
||||
mbedtls_ctr_drbg_init(&random_context);
|
||||
mbedtls_entropy_add_source(&entropy_context, entropy_hw_random_source, NULL, 134, MBEDTLS_ENTROPY_SOURCE_STRONG);
|
||||
mbedtls_ctr_drbg_seed(&random_context, mbedtls_entropy_func, &entropy_context, NULL, 0);
|
||||
|
||||
is_platform_initialized = true;
|
||||
}
|
||||
|
||||
void wireguard_random_bytes(void *bytes, size_t size) {
|
||||
uint8_t *out = (uint8_t *)bytes;
|
||||
mbedtls_ctr_drbg_random(&random_context, bytes, size);
|
||||
}
|
||||
|
||||
uint32_t wireguard_sys_now() {
|
||||
// Default to the LwIP system time
|
||||
return sys_now();
|
||||
}
|
||||
|
||||
void wireguard_tai64n_now(uint8_t *output) {
|
||||
// See https://cr.yp.to/libtai/tai64.html
|
||||
// 64 bit seconds from 1970 = 8 bytes
|
||||
// 32 bit nano seconds from current second
|
||||
|
||||
// Get timestamp. Note that the timestamp must be synced by NTP,
|
||||
// or at least preserved in NVS, not to go back after reset.
|
||||
// Otherwise, the WireGuard remote peer rejects handshake.
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
uint64_t millis = (tv.tv_sec * 1000LL + (tv.tv_usec / 1000LL));
|
||||
|
||||
// Split into seconds offset + nanos
|
||||
uint64_t seconds = 0x400000000000000aULL + (millis / 1000);
|
||||
uint32_t nanos = (millis % 1000) * 1000;
|
||||
U64TO8_BIG(output + 0, seconds);
|
||||
U32TO8_BIG(output + 8, nanos);
|
||||
}
|
||||
|
||||
bool wireguard_is_under_load() {
|
||||
return false;
|
||||
}
|
||||
|
71
lib/WireGuard-ESP32/src/wireguard-platform.h
Normal file
71
lib/WireGuard-ESP32/src/wireguard-platform.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Ported to ESP32 Arduino by Kenta Ida (fuga@fugafuga.org)
|
||||
* The original license is below:
|
||||
*
|
||||
* Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
*/
|
||||
|
||||
#ifndef _WIREGUARD_PLATFORM_H_
|
||||
#define _WIREGUARD_PLATFORM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Peers are allocated statically inside the device structure to avoid malloc
|
||||
#define WIREGUARD_MAX_PEERS 1
|
||||
#define WIREGUARD_MAX_SRC_IPS 2
|
||||
|
||||
// Per device limit on accepting (valid) initiation requests - per peer
|
||||
#define MAX_INITIATIONS_PER_SECOND (2)
|
||||
|
||||
//
|
||||
// Your platform integration needs to provide implementations of these functions
|
||||
//
|
||||
|
||||
void wireguard_platform_init();
|
||||
|
||||
// The number of milliseconds since system boot - for LwIP systems this could be sys_now()
|
||||
uint32_t wireguard_sys_now();
|
||||
|
||||
// Fill the supplied buffer with random data - random data is used for generating new session keys periodically
|
||||
void wireguard_random_bytes(void *bytes, size_t size);
|
||||
|
||||
// Get the current time in tai64n format - 8 byte seconds, 4 byte nano sub-second - see https://cr.yp.to/libtai/tai64.html for details
|
||||
// Output buffer passed is 12 bytes
|
||||
// The Wireguard implementation doesn't strictly need this to be a time, but instead an increasing value
|
||||
// The remote end of the Wireguard tunnel will use this value in handshake replay detection
|
||||
void wireguard_tai64n_now(uint8_t *output);
|
||||
|
||||
// Is the system under load - i.e. should we generate cookie reply message in response to initiation messages
|
||||
bool wireguard_is_under_load();
|
||||
|
||||
#endif /* _WIREGUARD_PLATFORM_H_ */
|
1129
lib/WireGuard-ESP32/src/wireguard.c
Normal file
1129
lib/WireGuard-ESP32/src/wireguard.c
Normal file
File diff suppressed because it is too large
Load Diff
287
lib/WireGuard-ESP32/src/wireguard.h
Normal file
287
lib/WireGuard-ESP32/src/wireguard.h
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Ported to ESP32 Arduino by Kenta Ida (fuga@fugafuga.org)
|
||||
* The original license is below:
|
||||
* Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
*/
|
||||
|
||||
#ifndef _WIREGUARD_H_
|
||||
#define _WIREGUARD_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Note: these are only required for definitions in device/peer for netif, udp_pcb, ip_addr_t and u16_t
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/arch.h"
|
||||
|
||||
// Platform-specific functions that need to be implemented per-platform
|
||||
#include "wireguard-platform.h"
|
||||
|
||||
// tai64n contains 64-bit seconds and 32-bit nano offset (12 bytes)
|
||||
#define WIREGUARD_TAI64N_LEN (12)
|
||||
// Auth algorithm is chacha20pol1305 which is 128bit (16 byte) authenticator
|
||||
#define WIREGUARD_AUTHTAG_LEN (16)
|
||||
// Hash algorithm is blake2s which makes 32 byte hashes
|
||||
#define WIREGUARD_HASH_LEN (32)
|
||||
// Public key algo is curve22519 which uses 32 byte keys
|
||||
#define WIREGUARD_PUBLIC_KEY_LEN (32)
|
||||
// Public key algo is curve22519 which uses 32 byte keys
|
||||
#define WIREGUARD_PRIVATE_KEY_LEN (32)
|
||||
// Symmetric session keys are chacha20/poly1305 which uses 32 byte keys
|
||||
#define WIREGUARD_SESSION_KEY_LEN (32)
|
||||
|
||||
// Timers / Limits
|
||||
#define WIREGUARD_COOKIE_LEN (16)
|
||||
#define COOKIE_SECRET_MAX_AGE (2 * 60)
|
||||
#define COOKIE_NONCE_LEN (24)
|
||||
|
||||
#define REKEY_AFTER_MESSAGES (1ULL << 60)
|
||||
#define REJECT_AFTER_MESSAGES (0xFFFFFFFFFFFFFFFFULL - (1ULL << 13))
|
||||
#define REKEY_AFTER_TIME (120)
|
||||
#define REJECT_AFTER_TIME (180)
|
||||
#define REKEY_TIMEOUT (5)
|
||||
#define KEEPALIVE_TIMEOUT (10)
|
||||
|
||||
struct wireguard_keypair {
|
||||
bool valid;
|
||||
bool initiator; // Did we initiate this session (send the initiation packet rather than sending the response packet)
|
||||
uint32_t keypair_millis;
|
||||
|
||||
uint8_t sending_key[WIREGUARD_SESSION_KEY_LEN];
|
||||
bool sending_valid;
|
||||
uint64_t sending_counter;
|
||||
|
||||
uint8_t receiving_key[WIREGUARD_SESSION_KEY_LEN];
|
||||
bool receiving_valid;
|
||||
|
||||
uint32_t last_tx;
|
||||
uint32_t last_rx;
|
||||
|
||||
uint32_t replay_bitmap;
|
||||
uint64_t replay_counter;
|
||||
|
||||
uint32_t local_index; // This is the index we generated for our end
|
||||
uint32_t remote_index; // This is the index on the other end
|
||||
};
|
||||
|
||||
struct wireguard_handshake {
|
||||
bool valid;
|
||||
bool initiator;
|
||||
uint32_t local_index;
|
||||
uint32_t remote_index;
|
||||
uint8_t ephemeral_private[WIREGUARD_PRIVATE_KEY_LEN];
|
||||
uint8_t remote_ephemeral[WIREGUARD_PUBLIC_KEY_LEN];
|
||||
uint8_t hash[WIREGUARD_HASH_LEN];
|
||||
uint8_t chaining_key[WIREGUARD_HASH_LEN];
|
||||
};
|
||||
|
||||
struct wireguard_allowed_ip {
|
||||
bool valid;
|
||||
ip_addr_t ip;
|
||||
ip_addr_t mask;
|
||||
};
|
||||
|
||||
struct wireguard_peer {
|
||||
bool valid; // Is this peer initialised?
|
||||
bool active; // Should we be actively trying to connect?
|
||||
|
||||
// This is the configured IP of the peer (endpoint)
|
||||
ip_addr_t connect_ip;
|
||||
u16_t connect_port;
|
||||
// This is the latest received IP/port
|
||||
ip_addr_t ip;
|
||||
u16_t port;
|
||||
// keep-alive interval in seconds, 0 is disable
|
||||
uint16_t keepalive_interval;
|
||||
|
||||
struct wireguard_allowed_ip allowed_source_ips[WIREGUARD_MAX_SRC_IPS];
|
||||
|
||||
uint8_t public_key[WIREGUARD_PUBLIC_KEY_LEN];
|
||||
uint8_t preshared_key[WIREGUARD_SESSION_KEY_LEN];
|
||||
|
||||
// Precomputed DH(Sprivi,Spubr) with device private key, and peer public key
|
||||
uint8_t public_key_dh[WIREGUARD_PUBLIC_KEY_LEN];
|
||||
|
||||
// Session keypairs
|
||||
struct wireguard_keypair curr_keypair;
|
||||
struct wireguard_keypair prev_keypair;
|
||||
struct wireguard_keypair next_keypair;
|
||||
|
||||
// 5.1 Silence is a Virtue: The responder keeps track of the greatest timestamp received per peer
|
||||
uint8_t greatest_timestamp[WIREGUARD_TAI64N_LEN];
|
||||
|
||||
// The active handshake that is happening
|
||||
struct wireguard_handshake handshake;
|
||||
|
||||
// Decrypted cookie from the responder
|
||||
uint32_t cookie_millis;
|
||||
uint8_t cookie[WIREGUARD_COOKIE_LEN];
|
||||
|
||||
// The latest mac1 we sent with initiation
|
||||
bool handshake_mac1_valid;
|
||||
uint8_t handshake_mac1[WIREGUARD_COOKIE_LEN];
|
||||
|
||||
// Precomputed keys for use in mac validation
|
||||
uint8_t label_cookie_key[WIREGUARD_SESSION_KEY_LEN];
|
||||
uint8_t label_mac1_key[WIREGUARD_SESSION_KEY_LEN];
|
||||
|
||||
// The last time we received a valid initiation message
|
||||
uint32_t last_initiation_rx;
|
||||
// The last time we sent an initiation message to this peer
|
||||
uint32_t last_initiation_tx;
|
||||
|
||||
// last_tx and last_rx of data packets
|
||||
uint32_t last_tx;
|
||||
uint32_t last_rx;
|
||||
|
||||
// We set this flag on RX/TX of packets if we think that we should initiate a new handshake
|
||||
bool send_handshake;
|
||||
};
|
||||
|
||||
struct wireguard_device {
|
||||
// Maybe have a "Device private" member to abstract these?
|
||||
struct netif *netif;
|
||||
struct udp_pcb *udp_pcb;
|
||||
|
||||
struct netif *underlying_netif;
|
||||
|
||||
uint8_t public_key[WIREGUARD_PUBLIC_KEY_LEN];
|
||||
uint8_t private_key[WIREGUARD_PRIVATE_KEY_LEN];
|
||||
|
||||
uint8_t cookie_secret[WIREGUARD_HASH_LEN];
|
||||
uint32_t cookie_secret_millis;
|
||||
|
||||
// Precalculated
|
||||
uint8_t label_cookie_key[WIREGUARD_SESSION_KEY_LEN];
|
||||
uint8_t label_mac1_key[WIREGUARD_SESSION_KEY_LEN];
|
||||
|
||||
// List of peers associated with this device
|
||||
struct wireguard_peer peers[WIREGUARD_MAX_PEERS];
|
||||
|
||||
bool valid;
|
||||
};
|
||||
|
||||
#define MESSAGE_INVALID 0
|
||||
#define MESSAGE_HANDSHAKE_INITIATION 1
|
||||
#define MESSAGE_HANDSHAKE_RESPONSE 2
|
||||
#define MESSAGE_COOKIE_REPLY 3
|
||||
#define MESSAGE_TRANSPORT_DATA 4
|
||||
|
||||
|
||||
// 5.4.2 First Message: Initiator to Responder
|
||||
struct message_handshake_initiation {
|
||||
uint8_t type;
|
||||
uint8_t reserved[3];
|
||||
uint32_t sender;
|
||||
uint8_t ephemeral[32];
|
||||
uint8_t enc_static[32 + WIREGUARD_AUTHTAG_LEN];
|
||||
uint8_t enc_timestamp[WIREGUARD_TAI64N_LEN + WIREGUARD_AUTHTAG_LEN];
|
||||
uint8_t mac1[WIREGUARD_COOKIE_LEN];
|
||||
uint8_t mac2[WIREGUARD_COOKIE_LEN];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
// 5.4.3 Second Message: Responder to Initiator
|
||||
struct message_handshake_response {
|
||||
uint8_t type;
|
||||
uint8_t reserved[3];
|
||||
uint32_t sender;
|
||||
uint32_t receiver;
|
||||
uint8_t ephemeral[32];
|
||||
uint8_t enc_empty[0 + WIREGUARD_AUTHTAG_LEN];
|
||||
uint8_t mac1[WIREGUARD_COOKIE_LEN];
|
||||
uint8_t mac2[WIREGUARD_COOKIE_LEN];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
// 5.4.7 Under Load: Cookie Reply Message
|
||||
struct message_cookie_reply {
|
||||
uint8_t type;
|
||||
uint8_t reserved[3];
|
||||
uint32_t receiver;
|
||||
uint8_t nonce[COOKIE_NONCE_LEN];
|
||||
uint8_t enc_cookie[WIREGUARD_COOKIE_LEN + WIREGUARD_AUTHTAG_LEN];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
// 5.4.6 Subsequent Messages: Transport Data Messages
|
||||
struct message_transport_data {
|
||||
uint8_t type;
|
||||
uint8_t reserved[3];
|
||||
uint32_t receiver;
|
||||
uint8_t counter[8];
|
||||
// Followed by encrypted data
|
||||
uint8_t enc_packet[];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
// Initialise the WireGuard system - need to call this before anything else
|
||||
void wireguard_init();
|
||||
bool wireguard_device_init(struct wireguard_device *device, const uint8_t *private_key);
|
||||
bool wireguard_peer_init(struct wireguard_device *device, struct wireguard_peer *peer, const uint8_t *public_key, const uint8_t *preshared_key);
|
||||
|
||||
struct wireguard_peer *peer_alloc(struct wireguard_device *device);
|
||||
uint8_t wireguard_peer_index(struct wireguard_device *device, struct wireguard_peer *peer);
|
||||
struct wireguard_peer *peer_lookup_by_pubkey(struct wireguard_device *device, uint8_t *public_key);
|
||||
struct wireguard_peer *peer_lookup_by_peer_index(struct wireguard_device *device, uint8_t peer_index);
|
||||
struct wireguard_peer *peer_lookup_by_receiver(struct wireguard_device *device, uint32_t receiver);
|
||||
struct wireguard_peer *peer_lookup_by_handshake(struct wireguard_device *device, uint32_t receiver);
|
||||
|
||||
void wireguard_start_session(struct wireguard_peer *peer, bool initiator);
|
||||
|
||||
void keypair_update(struct wireguard_peer *peer, struct wireguard_keypair *received_keypair);
|
||||
void keypair_destroy(struct wireguard_keypair *keypair);
|
||||
|
||||
struct wireguard_keypair *get_peer_keypair_for_idx(struct wireguard_peer *peer, uint32_t idx);
|
||||
bool wireguard_check_replay(struct wireguard_keypair *keypair, uint64_t seq);
|
||||
|
||||
uint8_t wireguard_get_message_type(const uint8_t *data, size_t len);
|
||||
|
||||
struct wireguard_peer *wireguard_process_initiation_message(struct wireguard_device *device, struct message_handshake_initiation *msg);
|
||||
bool wireguard_process_handshake_response(struct wireguard_device *device, struct wireguard_peer *peer, struct message_handshake_response *src);
|
||||
bool wireguard_process_cookie_message(struct wireguard_device *device, struct wireguard_peer *peer, struct message_cookie_reply *src);
|
||||
|
||||
bool wireguard_create_handshake_initiation(struct wireguard_device *device, struct wireguard_peer *peer, struct message_handshake_initiation *dst);
|
||||
bool wireguard_create_handshake_response(struct wireguard_device *device, struct wireguard_peer *peer, struct message_handshake_response *dst);
|
||||
void wireguard_create_cookie_reply(struct wireguard_device *device, struct message_cookie_reply *dst, const uint8_t *mac1, uint32_t index, uint8_t *source_addr_port, size_t source_length);
|
||||
|
||||
|
||||
bool wireguard_check_mac1(struct wireguard_device *device, const uint8_t *data, size_t len, const uint8_t *mac1);
|
||||
bool wireguard_check_mac2(struct wireguard_device *device, const uint8_t *data, size_t len, uint8_t *source_addr_port, size_t source_length, const uint8_t *mac2);
|
||||
|
||||
bool wireguard_expired(uint32_t created_millis, uint32_t valid_seconds);
|
||||
|
||||
void wireguard_encrypt_packet(uint8_t *dst, const uint8_t *src, size_t src_len, struct wireguard_keypair *keypair);
|
||||
bool wireguard_decrypt_packet(uint8_t *dst, const uint8_t *src, size_t src_len, uint64_t counter, struct wireguard_keypair *keypair);
|
||||
|
||||
bool wireguard_base64_decode(const char *str, uint8_t *out, size_t *outlen);
|
||||
bool wireguard_base64_encode(const uint8_t *in, size_t inlen, char *out, size_t *outlen);
|
||||
|
||||
#endif /* _WIREGUARD_H_ */
|
1028
lib/WireGuard-ESP32/src/wireguardif.c
Normal file
1028
lib/WireGuard-ESP32/src/wireguardif.c
Normal file
File diff suppressed because it is too large
Load Diff
137
lib/WireGuard-ESP32/src/wireguardif.h
Normal file
137
lib/WireGuard-ESP32/src/wireguardif.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Ported to ESP32 Arduino by Kenta Ida (fuga@fugafuga.org)
|
||||
* The original license is below:
|
||||
*
|
||||
* Copyright (c) 2021 Daniel Hope (www.floorsense.nz)
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Hope <daniel.hope@smartalock.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _WIREGUARDIF_H_
|
||||
#define _WIREGUARDIF_H_
|
||||
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
// Default MTU for WireGuard is 1420 bytes
|
||||
#define WIREGUARDIF_MTU (1420)
|
||||
|
||||
#define WIREGUARDIF_DEFAULT_PORT (51820)
|
||||
#define WIREGUARDIF_KEEPALIVE_DEFAULT (0xFFFF)
|
||||
|
||||
struct wireguardif_init_data {
|
||||
// Required: the private key of this WireGuard network interface
|
||||
const char *private_key;
|
||||
// Required: What UDP port to listen on
|
||||
u16_t listen_port;
|
||||
// Optional: restrict send/receive of encapsulated WireGuard traffic to this network interface only (NULL to use routing table)
|
||||
struct netif *bind_netif;
|
||||
};
|
||||
|
||||
struct wireguardif_peer {
|
||||
const char *public_key;
|
||||
// Optional pre-shared key (32 bytes) - make sure this is NULL if not to be used
|
||||
const uint8_t *preshared_key;
|
||||
// tai64n of largest timestamp we have seen during handshake to avoid replays
|
||||
uint8_t greatest_timestamp[12];
|
||||
|
||||
// Allowed ip/netmask (can add additional later but at least one is required)
|
||||
ip_addr_t allowed_ip;
|
||||
ip_addr_t allowed_mask;
|
||||
|
||||
// End-point details (may be blank)
|
||||
ip_addr_t endpoint_ip;
|
||||
u16_t endport_port;
|
||||
u16_t keep_alive;
|
||||
};
|
||||
|
||||
#define WIREGUARDIF_INVALID_INDEX (0xFF)
|
||||
|
||||
/* static struct netif wg_netif_struct = {0};
|
||||
* struct wireguard_interface wg;
|
||||
* wg.private_key = "abcdefxxx..xxxxx=";
|
||||
* wg.listen_port = 51820;
|
||||
* wg.bind_netif = NULL; // Pass netif to listen on, NULL for all interfaces
|
||||
*
|
||||
* netif = netif_add(&netif_struct, &ipaddr, &netmask, &gateway, &wg, &wireguardif_init, &ip_input);
|
||||
*
|
||||
* netif_set_up(wg_net);
|
||||
*
|
||||
* struct wireguardif_peer peer;
|
||||
* wireguardif_peer_init(&peer);
|
||||
* peer.public_key = "apoehc...4322abcdfejg=;
|
||||
* peer.preshared_key = NULL;
|
||||
* peer.allowed_ip = allowed_ip;
|
||||
* peer.allowed_mask = allowed_mask;
|
||||
*
|
||||
* // If you want to enable output connection
|
||||
* peer.endpoint_ip = peer_ip;
|
||||
* peer.endport_port = 12345;
|
||||
*
|
||||
* uint8_t wireguard_peer_index;
|
||||
* wireguardif_add_peer(netif, &peer, &wireguard_peer_index);
|
||||
*
|
||||
* if ((wireguard_peer_index != WIREGUARDIF_INVALID_INDEX) && !ip_addr_isany(&peer.endpoint_ip)) {
|
||||
* // Start outbound connection to peer
|
||||
* wireguardif_connect(wg_net, wireguard_peer_index);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
// Initialise a new WireGuard network interface (netif)
|
||||
err_t wireguardif_init(struct netif *netif);
|
||||
|
||||
// Shutdown a WireGuard network interface (netif)
|
||||
void wireguardif_shutdown(struct netif *netif);
|
||||
|
||||
// Helper to initialise the peer struct with defaults
|
||||
void wireguardif_peer_init(struct wireguardif_peer *peer);
|
||||
|
||||
// Add a new peer to the specified interface - see wireguard.h for maximum number of peers allowed
|
||||
// On success the peer_index can be used to reference this peer in future function calls
|
||||
err_t wireguardif_add_peer(struct netif *netif, struct wireguardif_peer *peer, u8_t *peer_index);
|
||||
|
||||
// Remove the given peer from the network interface
|
||||
err_t wireguardif_remove_peer(struct netif *netif, u8_t peer_index);
|
||||
|
||||
// Update the "connect" IP of the given peer
|
||||
err_t wireguardif_update_endpoint(struct netif *netif, u8_t peer_index, const ip_addr_t *ip, u16_t port);
|
||||
|
||||
// Try and connect to the given peer
|
||||
err_t wireguardif_connect(struct netif *netif, u8_t peer_index);
|
||||
|
||||
// Stop trying to connect to the given peer
|
||||
err_t wireguardif_disconnect(struct netif *netif, u8_t peer_index);
|
||||
|
||||
// Is the given peer "up"? A peer is up if it has a valid session key it can communicate with
|
||||
err_t wireguardif_peer_is_up(struct netif *netif, u8_t peer_index, ip_addr_t *current_ip, u16_t *current_port);
|
||||
|
||||
#endif /* _WIREGUARDIF_H_ */
|
Loading…
x
Reference in New Issue
Block a user