diff --git a/README.md b/README.md
index cbfd75c7..b1e8c85f 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,12 @@ improvements, please contact the author Rhys Weatherley via
Recent significant changes to the library
-----------------------------------------
+XXX 2018:
+
+* KeyRing for storing key pairs and other key material in EEPROM or Flash.
+* Add better functions to Curve25519 and Ed25519 for generating key pairs.
+* Noise and NoiseLink protocols.
+
Apr 2018:
* Acorn128 and Ascon128 authenticated ciphers (finalists in the CAESAR AEAD
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 4c60b831..55b4818f 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -661,6 +661,7 @@ INPUT = ../libraries/Crypto \
../libraries/NewHope \
../libraries/RingOscillatorNoiseSource \
../libraries/TransistorNoiseSource \
+ ../libraries/NoiseProtocol/src \
.
# This tag can be used to specify the character encoding of the source files
diff --git a/doc/crypto.dox b/doc/crypto.dox
index bc20712c..fb89fd2e 100644
--- a/doc/crypto.dox
+++ b/doc/crypto.dox
@@ -43,6 +43,7 @@ in the repository:
\li Message authenticators: Poly1305, GHASH, OMAC
\li Public key algorithms: Curve25519, Ed25519, P521
\li Random number generation: \link RNGClass RNG\endlink
+\li Storage of key pairs and other key material in EEPROM or Flash: KeyRing
Reduced memory versions of some algorithms (encryption is slower, but the
RAM required for the key schedule is less):
diff --git a/host/Crypto/Makefile b/host/Crypto/Makefile
index 7ac0189a..27acb308 100644
--- a/host/Crypto/Makefile
+++ b/host/Crypto/Makefile
@@ -6,12 +6,14 @@ SRCDIR = $(TOPDIR)/libraries/Crypto
SRCDIR2 = $(TOPDIR)/libraries/NewHope
SRCDIR3 = $(TOPDIR)/libraries/CryptoLW
SRCDIR4 = $(TOPDIR)/libraries/CryptoLegacy
+SRCDIR5 = $(TOPDIR)/libraries/NoiseProtocol
#VPATH = $(SRCDIR)
vpath %.cpp $(SRCDIR)
vpath %.cpp $(SRCDIR2)
vpath %.cpp $(SRCDIR3)/src
vpath %.cpp $(SRCDIR4)/src
+vpath %.cpp $(SRCDIR5)/src
vpath %.o .
vpath %.ino $(SRCDIR)/examples
vpath %.ino $(SRCDIR2)/examples
@@ -27,6 +29,7 @@ CPPFLAGS = \
-I$(TOPDIR)/libraries/CryptoLW/src \
-I$(TOPDIR)/libraries/CryptoLegacy/src \
-I$(TOPDIR)/libraries/NewHope \
+ -I$(TOPDIR)/libraries/NoiseProtocol \
-DHOST_BUILD
CXXFLAGS = -g -Wall $(CPPFLAGS)
@@ -58,6 +61,7 @@ SOURCES = \
GHASH.cpp \
Hash.cpp \
KeccakCore.cpp \
+ KeyRing.cpp \
NewHope.cpp \
NoiseSource.cpp \
OFB.cpp \
@@ -76,6 +80,39 @@ SOURCES = \
XOF.cpp \
XTS.cpp
+SOURCES += \
+ NoiseCipherState_AESGCM.cpp \
+ NoiseCipherState_ChaChaPoly.cpp \
+ NoiseCipherState.cpp \
+ NoiseDHState_Curve25519.cpp \
+ NoiseDHState.cpp \
+ NoiseHandshakeState.cpp \
+ Noise_IK_25519_AESGCM_SHA256.cpp \
+ Noise_IK_25519_ChaChaPoly_BLAKE2s.cpp \
+ Noise_IK_25519_ChaChaPoly_SHA256.cpp \
+ Noise_IK.cpp \
+ NoiseNamespace.cpp \
+ Noise_NNpsk0_25519_AESGCM_SHA256.cpp \
+ Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.cpp \
+ Noise_NNpsk0_25519_ChaChaPoly_SHA256.cpp \
+ Noise_NNpsk0.cpp \
+ Noise_Pipes_25519_AESGCM_SHA256.cpp \
+ Noise_Pipes_25519_ChaChaPoly_BLAKE2s.cpp \
+ Noise_Pipes_25519_ChaChaPoly_SHA256.cpp \
+ NoiseProtocolDescriptor.cpp \
+ NoiseSymmetricState_AESGCM_SHA256.cpp \
+ NoiseSymmetricState_ChaChaPoly_BLAKE2s.cpp \
+ NoiseSymmetricState_ChaChaPoly_SHA256.cpp \
+ NoiseSymmetricState.cpp \
+ Noise_XX_25519_AESGCM_SHA256.cpp \
+ Noise_XX_25519_ChaChaPoly_BLAKE2s.cpp \
+ Noise_XX_25519_ChaChaPoly_SHA256.cpp \
+ Noise_XX.cpp \
+ Noise_XXfallback_25519_AESGCM_SHA256.cpp \
+ Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.cpp \
+ Noise_XXfallback_25519_ChaChaPoly_SHA256.cpp \
+ Noise_XXfallback.cpp
+
SKETCHES = \
TestAcorn/TestAcorn.ino \
TestAES/TestAES.ino \
diff --git a/libraries/Crypto/Curve25519.cpp b/libraries/Crypto/Curve25519.cpp
index 84744f04..78f853d2 100644
--- a/libraries/Crypto/Curve25519.cpp
+++ b/libraries/Crypto/Curve25519.cpp
@@ -70,12 +70,15 @@
* algorithms with the curve. Normally applications should use dh1()
* and dh2() directly instead.
*
+ * The secret \a s value may point to a key pair that was generated by the
+ * Curve25519::generateKeyPair() function.
+ *
* \return Returns true if the function was evaluated; false if \a x is
* not a proper member of the field modulo (2^255 - 19).
*
* Reference: RFC 7748
*
- * \sa dh1(), dh2()
+ * \sa dh1(), dh2(), generateKeyPair()
*/
bool Curve25519::eval(uint8_t result[32], const uint8_t s[32], const uint8_t x[32])
{
@@ -297,6 +300,19 @@ bool Curve25519::dh2(uint8_t k[32], uint8_t f[32])
return (bool)((weak ^ 0x01) & 0x01);
}
+/**
+ * \brief Generatea a key pair for the Curve25519 algorithm.
+ *
+ * \param keyPair Buffer that returns the key pair, consisting of the
+ * 32-byte private key followed by the 32-byte public key.
+ *
+ * \sa eval()
+ */
+void Curve25519::generateKeyPair(uint8_t keyPair[64])
+{
+ dh1(keyPair + 32, keyPair);
+}
+
/**
* \brief Determines if a Curve25519 point is weak for contributory behaviour.
*
diff --git a/libraries/Crypto/Curve25519.h b/libraries/Crypto/Curve25519.h
index b95a9fae..74cc1abd 100644
--- a/libraries/Crypto/Curve25519.h
+++ b/libraries/Crypto/Curve25519.h
@@ -35,6 +35,8 @@ public:
static void dh1(uint8_t k[32], uint8_t f[32]);
static bool dh2(uint8_t k[32], uint8_t f[32]);
+ static void generateKeyPair(uint8_t keyPair[64]);
+
#if defined(TEST_CURVE25519_FIELD_OPS)
public:
#else
diff --git a/libraries/Crypto/Ed25519.cpp b/libraries/Crypto/Ed25519.cpp
index 5732e73b..acb5a28e 100644
--- a/libraries/Crypto/Ed25519.cpp
+++ b/libraries/Crypto/Ed25519.cpp
@@ -64,6 +64,19 @@
* }
* \endcode
*
+ * As an alternative, the private and public components of the key pair
+ * can be generated as a single 64-byte value:
+ *
+ * \code
+ * uint8_t keyPair[64];
+ * Ed25519::generateKeyPair(keyPair);
+ * Ed25519::sign(signature, keyPair, message, N);
+ * \endcode
+ *
+ * The 64-byte key pair consists of the 32-byte private key followed by
+ * the 32-byte public key. This should be compatible with other libraries
+ * that produce and use 64-byte Ed25519 key values.
+ *
* \note The public functions in this class need a substantial amount of
* stack space to store intermediate results while the curve function is
* being evaluated. About 1.5k of free stack space is recommended for safety.
@@ -173,6 +186,18 @@ void Ed25519::sign(uint8_t signature[64], const uint8_t privateKey[32],
clean(rB);
}
+/**
+ * \fn void Ed25519::sign(uint8_t signature[64], const uint8_t keyPair[64], const void *message, size_t len)
+ * \brief Signs a message using a specific Ed25519 key pair.
+ *
+ * \param signature The signature value.
+ * \param keyPair The key pair to use to sign the message.
+ * \param message Points to the message to be signed.
+ * \param len The length of the \a message to be signed.
+ *
+ * \sa verify(), generateKeyPair()
+ */
+
/**
* \brief Verifies a signature using a specific Ed25519 public key.
*
@@ -271,6 +296,20 @@ void Ed25519::derivePublicKey(uint8_t publicKey[32], const uint8_t privateKey[32
clean(ptA);
}
+/**
+ * \brief Generatea a key pair for the Ed25519 algorithm.
+ *
+ * \param keyPair Buffer that returns the key pair, consisting of the
+ * 32-byte private key followed by the 32-byte public key.
+ *
+ * \sa sign()
+ */
+void Ed25519::generateKeyPair(uint8_t keyPair[64])
+{
+ generatePrivateKey(keyPair);
+ derivePublicKey(keyPair + 32, keyPair);
+}
+
/**
* \brief Reduces a number modulo q that was specified in a 512 bit buffer.
*
diff --git a/libraries/Crypto/Ed25519.h b/libraries/Crypto/Ed25519.h
index bbdd9f20..b15844cb 100644
--- a/libraries/Crypto/Ed25519.h
+++ b/libraries/Crypto/Ed25519.h
@@ -32,12 +32,16 @@ public:
static void sign(uint8_t signature[64], const uint8_t privateKey[32],
const uint8_t publicKey[32], const void *message,
size_t len);
+ static void sign(uint8_t signature[64], const uint8_t keyPair[64],
+ const void *message, size_t len);
static bool verify(const uint8_t signature[64], const uint8_t publicKey[32],
const void *message, size_t len);
static void generatePrivateKey(uint8_t privateKey[32]);
static void derivePublicKey(uint8_t publicKey[32], const uint8_t privateKey[32]);
+ static void generateKeyPair(uint8_t keyPair[64]);
+
private:
// Constructor and destructor are private - cannot instantiate this class.
Ed25519();
@@ -68,4 +72,10 @@ private:
static void deriveKeys(SHA512 *hash, limb_t *a, const uint8_t privateKey[32]);
};
+inline void Ed25519::sign(uint8_t signature[64], const uint8_t keyPair[64],
+ const void *message, size_t len)
+{
+ sign(signature, keyPair, keyPair + 32, message, len);
+}
+
#endif
diff --git a/libraries/Crypto/KeyRing.cpp b/libraries/Crypto/KeyRing.cpp
new file mode 100644
index 00000000..9ea99159
--- /dev/null
+++ b/libraries/Crypto/KeyRing.cpp
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "KeyRing.h"
+
+/**
+ * \class KeyRing KeyRing.h
+ * \brief Permanent storage for key material.
+ *
+ * This class provides permanent storage for local key pairs, remote public
+ * keys, shared symmetric keys, and other data on a device. Other data may
+ * be certificates, configuration data, or any other information that
+ * isn't strictly key material.
+ *
+ * As an example, the following code will generate a new Curve25519
+ * key pair and save it into permanent storage as the default key pair
+ * for the device:
+ *
+ * \code
+ * uint8_t keyPair[64];
+ * Curve25519::generateKeyPair(keyPair);
+ * KeyRing::setLocalKeyPair(KeyRing::LocalCurve25519Default, keyPair, 64);
+ * \endcode
+ *
+ * Later, when the application needs the key pair it does the following:
+ *
+ * \code
+ * uint8_t keyPair[64];
+ * if (!KeyRing::getLocalKeyPair(KeyRing::LocalCurve25519Default, keyPair, 64)) {
+ * Serial.println("Curve25519 key pair not found!");
+ * } else {
+ * // Make use of the key pair.
+ * ...
+ * }
+ * \endcode
+ *
+ * The key ring data is not encrypted in the permanent storage, so the
+ * data may be compromised if the device is captured. The application can
+ * arrange to encrypt the values separately before calling the set functions
+ * in this class.
+ *
+ * The data is not encrypted by default because it creates a chicken-and-egg
+ * problem: where is the encryption key itself stored if the device does
+ * not have some way to enter a passphrase at runtime? We therefore leave
+ * the issue of key ring encryption up to the application.
+ *
+ * The amount of key data that can be stored is limited by the size of
+ * the permanent storage mechanism on the device:
+ *
+ * \li AVR devices will use no more than 1/2 of the available EEPROM
+ * space, starting at the end of EEPROM and working backwards.
+ * \li Arduino Due and ESP8266 allocate up to 8K of flash memory for key data.
+ * \li ESP32 storage is built on top of that chip's Non-Volatile Storage (NVS)
+ * mechanism, and is limited only by the maximum NVS size.
+ *
+ * If a device is not currently supported, then requests to store values
+ * in the key ring will fail. Requests to retrieve values from the key
+ * ring will return nothing.
+ */
+
+/**
+ * \var KeyRing::LocalCurve25519Default
+ * \brief Identifier for the default local Curve25519 key pair on the device.
+ */
+
+/**
+ * \var KeyRing::RemoteCurve25519Default
+ * \brief Identifier for the default remote Curve25519 public key for the
+ * primary remote device that this device will be communicating with.
+ */
+
+/**
+ * \var KeyRing::LocalEd25519Default
+ * \brief Identifier for the default local Ed25519 key pair on the device.
+ */
+
+/**
+ * \var KeyRing::RemoteEd25519Default
+ * \brief Identifier for the default remote Ed25519 public key for the
+ * primary remote device that this device will be communicating with.
+ */
+
+/**
+ * \fn bool KeyRing::setLocalKeyPair(uint16_t id, const void *pair, size_t size)
+ * \brief Sets a local key pair in permanent storage.
+ *
+ * \param id Identifier for the key pair to distinguish multiple key pairs
+ * in the permanent storage.
+ * \param pair Points to the key pair value, which is assumed to be the
+ * private key followed by the public key.
+ * \param size Size of the key pair, including both the private and public
+ * components.
+ *
+ * \return Returns true if the key pair was stored, or false if there is
+ * insufficient space to store the key pair, or this platform does not have
+ * permanent storage available.
+ *
+ * \sa getLocalKeyPair()
+ */
+
+/**
+ * \fn size_t KeyRing::getLocalKeyPair(uint16_t id, void *pair, size_t maxSize)
+ * \brief Gets a local key pair from permanent storage.
+ *
+ * \param id Identifier for the key pair to distinguish multiple key pairs
+ * in the permanent storage.
+ * \param pair Points to the buffer to retrieve the key pair value, which
+ * is assumed to consist of the private key followed by the public key.
+ * \param maxSize Maximum size of the \a pair buffer which may be larger
+ * than the actual key pair size, to support the retrieval of variable-length
+ * key pairs.
+ *
+ * \return The actual number of bytes in the key pair, or zero if the key
+ * pair was not found.
+ *
+ * The companion function getLocalKeyPairSize() can be used to query the
+ * size of the key pair before it is retrieved.
+ *
+ * \sa getLocalKeyPairSize(), setLocalKeyPair()
+ */
+
+/**
+ * \fn size_t KeyRing::getLocalKeyPairSize(uint16_t id)
+ * \brief Gets the size of a local key pair in permanent storage.
+ *
+ * \param id Identifier for the key pair to distinguish multiple key pairs
+ * in the permanent storage.
+ *
+ * \return The number of bytes of data that are stored for the key pair,
+ * or zero if there is no key pair currently associated with \a id.
+ *
+ * \sa getLocalKeyPair()
+ */
+
+/**
+ * \fn void KeyRing::removeLocalKeyPair(uint16_t id)
+ * \brief Removes a local key pair from permanent storage.
+ *
+ * \param id Identifier for the key pair to distinguish multiple key pairs
+ * in the permanent storage.
+ *
+ * The key pair value will be overwritten with 0xFF bytes to erase it.
+ * However, this may not be sufficient to completely remove all trace of
+ * the key pair from flash memory or EEPROM. If the underlying storage
+ * mechanism is performing wear-levelling, then it may leave older copies
+ * of the value in unused pages when new values are written.
+ */
+
+/**
+ * \fn bool KeyRing::setRemotePublicKey(uint16_t id, const void *key, size_t size)
+ * \brief Sets a remote public key in permanent storage.
+ *
+ * \param id Identifier for the remote public key to distinguish multiple
+ * public keys in the permanent storage.
+ * \param key Points to the public key value.
+ * \param size Size of the public key value in bytes.
+ *
+ * \return Returns true if the public key was stored, or false if there is
+ * insufficient space to store the public key, or this platform does not have
+ * permanent storage available.
+ *
+ * \sa getRemotePublicKey()
+ */
+
+/**
+ * \fn size_t KeyRing::getRemotePublicKey(uint16_t id, void *key, size_t maxSize)
+ * \brief Gets a remote public key from permanent storage.
+ *
+ * \param id Identifier for the remote public key to distinguish multiple
+ * public keys in the permanent storage.
+ * \param key Points to the buffer to retrieve the public key value.
+ * \param maxSize Maximum size of the \a key buffer which may be larger
+ * than the actual public key size, to support the retrieval of
+ * variable-length public keys.
+ *
+ * \return The actual number of bytes in the public key, or zero if the
+ * public key was not found.
+ *
+ * The companion function getRemotePublicKeySize() can be used to query the
+ * size of the public key before it is retrieved.
+ *
+ * \sa getRemotePublicKeySize(), setRemotePublicKey()
+ */
+
+/**
+ * \fn size_t KeyRing::getRemotePublicKeySize(uint16_t id)
+ * \brief Gets the size of a remote public key in permanent storage.
+ *
+ * \param id Identifier for the remote public key to distinguish multiple
+ * public keys in the permanent storage.
+ *
+ * \return The number of bytes of data that are stored for the public key,
+ * or zero if there is no public key currently associated with \a id.
+ *
+ * \sa getRemotePublicKey()
+ */
+
+/**
+ * \fn void KeyRing::removeRemotePublicKey(uint16_t id)
+ * \brief Removes a remote public key from permanent storage.
+ *
+ * \param id Identifier for the remote public key to distinguish multiple
+ * public keys in the permanent storage.
+ */
+
+/**
+ * \fn bool KeyRing::setSharedSymmetricKey(uint16_t id, const void *key, size_t size)
+ * \brief Sets a shared symmetric key in permanent storage.
+ *
+ * \param id Identifier for the shared symmetric key to distinguish multiple
+ * keys in the permanent storage.
+ * \param key Points to the shared symmetric key value.
+ * \param size Size of the shared symmetric key value in bytes.
+ *
+ * \return Returns true if the shared symmetric key was stored, or false if
+ * there is insufficient space to store the key, or this platform does not
+ * have permanent storage available.
+ *
+ * \sa getSharedSymmetricKey()
+ */
+
+/**
+ * \fn size_t KeyRing::getSharedSymmetricKey(uint16_t id, void *key, size_t maxSize)
+ * \brief Gets a shared symmetric key from permanent storage.
+ *
+ * \param id Identifier for the shared symmetric key to distinguish multiple
+ * keys in the permanent storage.
+ * \param key Points to the buffer to retrieve the shared symmetric key value.
+ * \param maxSize Maximum size of the \a key buffer which may be larger
+ * than the actual shared symmetric key size, to support the retrieval of
+ * variable-length keys.
+ *
+ * \return The actual number of bytes in the shared symmetric key,
+ * or zero if the key was not found.
+ *
+ * The companion function getSharedSymmetricKeySize() can be used to
+ * query the size of the shared symmetric key before it is retrieved.
+ *
+ * \sa getSharedSymmetricKeySize(), setSharedSymmetricKey()
+ */
+
+/**
+ * \fn size_t KeyRing::getSharedSymmetricKeySize(uint16_t id)
+ * \brief Gets the size of a shared symmetric key in permanent storage.
+ *
+ * \param id Identifier for the shared symmetric key to distinguish multiple
+ * keys in the permanent storage.
+ *
+ * \return The number of bytes of data that are stored for the shared
+ * symmetric key, or zero if there is no key currently associated with \a id.
+ *
+ * \sa getSharedSymmetricKey()
+ */
+
+/**
+ * \fn void KeyRing::removeSharedSymmetricKey(uint16_t id)
+ * \brief Removes a shared symmetric key from permanent storage.
+ *
+ * \param id Identifier for the shared symmetric key to distinguish multiple
+ * keys in the permanent storage.
+ *
+ * The symmetric key value will be overwritten with 0xFF bytes to erase it.
+ * However, this may not be sufficient to completely remove all trace of
+ * the key from flash memory or EEPROM. If the underlying storage mechanism
+ * is performing wear-levelling, then it may leave older copies of the value
+ * in unused pages when new values are written.
+ */
+
+/**
+ * \fn bool KeyRing::setOtherData(uint16_t id, const void *data, size_t size);
+ * \brief Sets an arbitrary data value in permanent storage.
+ *
+ * \param id Identifier for the data value to distinguish multiple values
+ * in the permanent storage.
+ * \param data Points to the data value to store.
+ * \param size Size of the data value in bytes.
+ *
+ * \return Returns true if the data value was stored, or false if there is
+ * insufficient space to store the value, or this platform does not have
+ * permanent storage available.
+ *
+ * \sa getOtherData()
+ */
+
+/**
+ * \fn size_t KeyRing::getOtherData(uint16_t id, void *data, size_t maxSize)
+ * \brief Gets an arbitrary data value from permanent storage.
+ *
+ * \param id Identifier for the data value to distinguish multiple values
+ * in the permanent storage.
+ * \param data Points to the buffer to retrieve the data value.
+ * \param maxSize Maximum size of the \a data buffer which may be larger
+ * than the actual data value size, to support the retrieval of
+ * variable-length values.
+ *
+ * \return The actual number of bytes in the data value, or zero if the value
+ * was not found.
+ *
+ * The companion function getOtherDataSize() can be used to query the size of
+ * the data value before it is retrieved.
+ *
+ * \sa getOtherDataSize(), setOtherData()
+ */
+
+/**
+ * \fn size_t KeyRing::getOtherDataSize(uint16_t id)
+ * \brief Gets the size of an arbitrary data value in permanent storage.
+ *
+ * \param id Identifier for the data value to distinguish multiple values
+ * in the permanent storage.
+ *
+ * \return The number of bytes of data that are stored for the value,
+ * or zero if there is no value currently associated with \a id.
+ *
+ * \sa getOtherData()
+ */
+
+/**
+ * \fn void KeyRing::removeOtherData(uint16_t id)
+ * \brief Removes an arbitrary data value from permanent storage.
+ *
+ * \param id Identifier for the data value to distinguish multiple values
+ * in the permanent storage.
+ */
+
+bool KeyRing::set(uint16_t id, uint8_t type, const void *data, size_t size)
+{
+ // TODO
+ return false;
+}
+
+size_t KeyRing::get(uint16_t id, uint8_t type, void *data, size_t maxSize)
+{
+ // TODO
+ return 0;
+}
+
+size_t KeyRing::getSize(uint16_t id, uint8_t type)
+{
+ // TODO
+ return 0;
+}
+
+void KeyRing::remove(uint16_t id, uint8_t type)
+{
+ // TODO
+}
diff --git a/libraries/Crypto/KeyRing.h b/libraries/Crypto/KeyRing.h
new file mode 100644
index 00000000..906cda6c
--- /dev/null
+++ b/libraries/Crypto/KeyRing.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef KEY_RING_h
+#define KEY_RING_h
+
+#include
+#include
+
+class KeyRing
+{
+private:
+ KeyRing() {}
+ ~KeyRing() {}
+
+public:
+ static bool setLocalKeyPair
+ (uint16_t id, const void *pair, size_t size);
+ static size_t getLocalKeyPair
+ (uint16_t id, void *pair, size_t maxSize);
+ static size_t getLocalKeyPairSize(uint16_t id);
+ static void removeLocalKeyPair(uint16_t id);
+
+ static bool setRemotePublicKey
+ (uint16_t id, const void *key, size_t size);
+ static size_t getRemotePublicKey
+ (uint16_t id, void *key, size_t maxSize);
+ static size_t getRemotePublicKeySize(uint16_t id);
+ static void removeRemotePublicKey(uint16_t id);
+
+ static bool setSharedSymmetricKey
+ (uint16_t id, const void *key, size_t size);
+ static size_t getSharedSymmetricKey
+ (uint16_t id, void *key, size_t maxSize);
+ static size_t getSharedSymmetricKeySize(uint16_t id);
+ static void removeSharedSymmetricKey(uint16_t id);
+
+ static bool setOtherData
+ (uint16_t id, const void *data, size_t size);
+ static size_t getOtherData
+ (uint16_t id, void *data, size_t maxSize);
+ static size_t getOtherDataSize(uint16_t id);
+ static void removeOtherData(uint16_t id);
+
+ static const uint16_t LocalCurve25519Default = 0x4301; // 'C', 0x01
+ static const uint16_t RemoteCurve25519Default = 0x6301; // 'c', 0x01
+
+ static const uint16_t LocalEd25519Default = 0x4501; // 'E', 0x01
+ static const uint16_t RemoteEd25519Default = 0x6501; // 'e', 0x01
+
+private:
+ static bool set(uint16_t id, uint8_t type, const void *data, size_t size);
+ static size_t get(uint16_t id, uint8_t type, void *data, size_t maxSize);
+ static size_t getSize(uint16_t id, uint8_t type);
+ static void remove(uint16_t id, uint8_t type);
+};
+
+inline bool KeyRing::setLocalKeyPair
+ (uint16_t id, const void *pair, size_t size)
+{
+ return set(id, 0, pair, size);
+}
+
+inline size_t KeyRing::getLocalKeyPair
+ (uint16_t id, void *pair, size_t maxSize)
+{
+ return get(id, 0, pair, maxSize);
+}
+
+inline size_t KeyRing::getLocalKeyPairSize(uint16_t id)
+{
+ return getSize(id, 0);
+}
+
+inline void KeyRing::removeLocalKeyPair(uint16_t id)
+{
+ remove(id, 0);
+}
+
+inline bool KeyRing::setRemotePublicKey
+ (uint16_t id, const void *key, size_t size)
+{
+ return set(id, 1, key, size);
+}
+
+inline size_t KeyRing::getRemotePublicKey
+ (uint16_t id, void *key, size_t maxSize)
+{
+ return get(id, 1, key, maxSize);
+}
+
+inline size_t KeyRing::getRemotePublicKeySize(uint16_t id)
+{
+ return getSize(id, 1);
+}
+
+inline void KeyRing::removeRemotePublicKey(uint16_t id)
+{
+ remove(id, 1);
+}
+
+inline bool KeyRing::setSharedSymmetricKey
+ (uint16_t id, const void *key, size_t size)
+{
+ return set(id, 2, key, size);
+}
+
+inline size_t KeyRing::getSharedSymmetricKey
+ (uint16_t id, void *key, size_t maxSize)
+{
+ return get(id, 2, key, maxSize);
+}
+
+inline size_t KeyRing::getSharedSymmetricKeySize(uint16_t id)
+{
+ return getSize(id, 2);
+}
+
+inline void KeyRing::removeSharedSymmetricKey(uint16_t id)
+{
+ remove(id, 2);
+}
+
+inline bool KeyRing::setOtherData
+ (uint16_t id, const void *data, size_t size)
+{
+ return set(id, 3, data, size);
+}
+
+inline size_t KeyRing::getOtherData
+ (uint16_t id, void *data, size_t maxSize)
+{
+ return get(id, 3, data, maxSize);
+}
+
+inline size_t KeyRing::getOtherDataSize(uint16_t id)
+{
+ return getSize(id, 3);
+}
+
+inline void KeyRing::removeOtherData(uint16_t id)
+{
+ remove(id, 3);
+}
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseCipherState.cpp b/libraries/NoiseProtocol/src/NoiseCipherState.cpp
new file mode 100644
index 00000000..36f76d2a
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseCipherState.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseCipherState.h"
+
+/**
+ * \class NoiseCipherState NoiseCipherState.h
+ * \brief Abstract base class for the Noise protocol's cipher state.
+ *
+ * This class is abstract. The caller should instantiate a subclass like
+ * NoiseCipherState_ChaChaPoly or NoiseCipherState_AESGCM to choose the
+ * specific algorithm to use in the cipher state.
+ *
+ * Normally the application will not instantiate instances of this
+ * class or its subclasses directly. Instead, it will call
+ * NoiseHandshakeState::split() at the end of the handshake phase
+ * of a connection.
+ */
+
+/**
+ * \fn NoiseCipherState::NoiseCipherState()
+ * \brief Constructs a new cipher object.
+ */
+
+/**
+ * \brief Destroys this cipher object.
+ */
+NoiseCipherState::~NoiseCipherState()
+{
+}
+
+/**
+ * \fn void NoiseCipherState::setNonce(uint64_t nonce)
+ * \brief Sets the nonce value for the next packet to be encrypted or
+ * decrypted.
+ *
+ * \param nonce The nonce value between 0 and 2^64 - 2.
+ *
+ * You won't need to use this function on reliable transports like TCP.
+ * You may need to use this function on unreliable transports like UDP.
+ * Care must be taken not to use the same nonce with multiple packets,
+ * and to reject duplicate packets.
+ */
+
+/**
+ * \fn int NoiseCipherState::encryptPacket(void *output, size_t outputSize, const void *input, size_t inputSize)
+ * \brief Encrypts a packet in a Noise transport session.
+ *
+ * \param output Output buffer to write the ciphertext and MAC to.
+ * \param outputSize Available space in the \a output buffer.
+ * \param input Input buffer containing the plaintext to be encrypted.
+ * \param inputSize Number of bytes of plaintext.
+ *
+ * \return The number of bytes that were written to \a output.
+ * \return -1 if \a outputSize is not large enough to contain the
+ * ciphertext and MAC.
+ *
+ * MAC values will add an extra 16 bytes to the size of the packet.
+ *
+ * \sa decryptPacket()
+ */
+
+/**
+ * \fn int NoiseCipherState::decryptPacket(void *output, size_t outputSize, const void *input, size_t inputSize)
+ * \brief Decrypts a packet in a Noise transport session.
+ *
+ * \param output Output buffer to write the plaintext to.
+ * \param outputSize Available space in the \a output buffer.
+ * \param input Input buffer containing the ciphertext and MAC.
+ * \param inputSize Number of bytes of ciphertext plus the MAC.
+ *
+ * \return The number of bytes that were written to \a output.
+ * \return -1 if \a outputSize is not large enough to contain the plaintext.
+ * \return -1 if the MAC check failed; the plaintext output will be invalid.
+ *
+ * \sa encryptPacket()
+ */
+
+/**
+ * \fn void NoiseCipherState::rekey()
+ * \brief Rekey the cipher object.
+ *
+ * This function should be called periodically to refresh the key that is
+ * used to encrypt data. This avoids the same key being used over and over
+ * as the more data that is encrypted with the same key, the more likely
+ * statistical trends may reveal themselves to an attacker.
+ */
+
+/**
+ * \fn void NoiseCipherState::clear()
+ * \brief Destroys sensitive data in this cipher object.
+ *
+ * After this function is called, no more packets can be encrypted or
+ * decrypted and a new cipher object must be created.
+ */
diff --git a/libraries/NoiseProtocol/src/NoiseCipherState.h b/libraries/NoiseProtocol/src/NoiseCipherState.h
new file mode 100644
index 00000000..b90b4c2f
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseCipherState.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_CIPHER_STATE_h
+#define NOISE_CIPHER_STATE_h
+
+#include
+#include
+
+class NoiseCipherState
+{
+public:
+ NoiseCipherState() {}
+ virtual ~NoiseCipherState();
+
+ virtual void setNonce(uint64_t nonce) = 0;
+
+ virtual int encryptPacket
+ (void *output, size_t outputSize,
+ const void *input, size_t inputSize) = 0;
+ virtual int decryptPacket
+ (void *output, size_t outputSize,
+ const void *input, size_t inputSize) = 0;
+
+ virtual void rekey() = 0;
+
+ virtual void clear() = 0;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseCipherState_AESGCM.cpp b/libraries/NoiseProtocol/src/NoiseCipherState_AESGCM.cpp
new file mode 100644
index 00000000..5344ef00
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseCipherState_AESGCM.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseCipherState_AESGCM.h"
+#include "Crypto.h"
+#include
+
+/**
+ * \class NoiseCipherState_AESGCM NoiseCipherState_AESGCM.h
+ * \brief Implementation of the AESGCM cipher
+ */
+
+/**
+ * \brief Constructs a new AESGCM cipher object.
+ *
+ * \param key The 256-bit key for the cipher object.
+ */
+NoiseCipherState_AESGCM::NoiseCipherState_AESGCM(const uint8_t key[32])
+{
+ cipher.setKey(key, 32);
+ n = 0;
+}
+
+/**
+ * \brief Destroys this AESGCM cipher object.
+ */
+NoiseCipherState_AESGCM::~NoiseCipherState_AESGCM()
+{
+ clean(&n, sizeof(n));
+}
+
+void NoiseCipherState_AESGCM::setNonce(uint64_t nonce)
+{
+ n = nonce;
+}
+
+// Import from NoiseSymmetricState_AESGCM_SHA256.cpp.
+void noiseAESGCMFormatIV(uint8_t iv[12], uint64_t n);
+
+int NoiseCipherState_AESGCM::encryptPacket
+ (void *output, size_t outputSize, const void *input, size_t inputSize)
+{
+ if (outputSize < 16 || (outputSize - 16) < inputSize)
+ return -1;
+ uint8_t iv[12];
+ noiseAESGCMFormatIV(iv, n);
+ cipher.setIV(iv, sizeof(iv));
+ cipher.encrypt((uint8_t *)output, (const uint8_t *)input, inputSize);
+ cipher.computeTag(((uint8_t *)output) + inputSize, 16);
+ ++n;
+ return inputSize + 16;
+}
+
+int NoiseCipherState_AESGCM::decryptPacket
+ (void *output, size_t outputSize, const void *input, size_t inputSize)
+{
+ if (inputSize < 16 || outputSize < (inputSize - 16))
+ return -1;
+ uint8_t iv[12];
+ noiseAESGCMFormatIV(iv, n);
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.decrypt((uint8_t *)output, (const uint8_t *)input, outputSize);
+ if (cipher.checkTag(((const uint8_t *)input) + outputSize, 16)) {
+ ++n;
+ return outputSize;
+ }
+ memset(output, 0, outputSize); // Destroy the output if the tag is invalid.
+ return -1;
+}
+
+void NoiseCipherState_AESGCM::rekey()
+{
+ uint8_t k[32];
+ static uint8_t const iv[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+ memset(k, 0, sizeof(k));
+ cipher.setIV(iv, sizeof(iv));
+ cipher.encrypt(k, k, sizeof(k));
+ cipher.setKey(k, sizeof(k));
+ clean(k);
+}
+
+void NoiseCipherState_AESGCM::clear()
+{
+ cipher.clear();
+ n = 0;
+}
diff --git a/libraries/NoiseProtocol/src/NoiseCipherState_AESGCM.h b/libraries/NoiseProtocol/src/NoiseCipherState_AESGCM.h
new file mode 100644
index 00000000..8b62d745
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseCipherState_AESGCM.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_CIPHER_STATE_AESGCM_h
+#define NOISE_CIPHER_STATE_AESGCM_h
+
+#include "NoiseCipherState.h"
+#include "AES.h"
+#include "GCM.h"
+
+class NoiseCipherState_AESGCM : public NoiseCipherState
+{
+public:
+ explicit NoiseCipherState_AESGCM(const uint8_t key[32]);
+ virtual ~NoiseCipherState_AESGCM();
+
+ void setNonce(uint64_t nonce);
+
+ int encryptPacket
+ (void *output, size_t outputSize,
+ const void *input, size_t inputSize);
+ int decryptPacket
+ (void *output, size_t outputSize,
+ const void *input, size_t inputSize);
+
+ void rekey();
+
+ void clear();
+
+private:
+ GCM cipher;
+ uint64_t n;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseCipherState_ChaChaPoly.cpp b/libraries/NoiseProtocol/src/NoiseCipherState_ChaChaPoly.cpp
new file mode 100644
index 00000000..2a600a6b
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseCipherState_ChaChaPoly.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseCipherState_ChaChaPoly.h"
+#include "Crypto.h"
+#include "utility/EndianUtil.h"
+#include
+
+/**
+ * \class NoiseCipherState_ChaChaPoly NoiseCipherState_ChaChaPoly.h
+ * \brief Implementation of the ChaChaPoly cipher
+ */
+
+/**
+ * \brief Constructs a new ChaChaPoly cipher object.
+ *
+ * \param key The 256-bit key for the cipher object.
+ */
+NoiseCipherState_ChaChaPoly::NoiseCipherState_ChaChaPoly(const uint8_t key[32])
+{
+ cipher.setKey(key, 32);
+ n = 0;
+}
+
+/**
+ * \brief Destroys this ChaChaPoly cipher object.
+ */
+NoiseCipherState_ChaChaPoly::~NoiseCipherState_ChaChaPoly()
+{
+ clean(&n, sizeof(n));
+}
+
+void NoiseCipherState_ChaChaPoly::setNonce(uint64_t nonce)
+{
+ n = nonce;
+}
+
+int NoiseCipherState_ChaChaPoly::encryptPacket
+ (void *output, size_t outputSize, const void *input, size_t inputSize)
+{
+ if (outputSize < 16 || (outputSize - 16) < inputSize)
+ return -1;
+ uint64_t iv = htole64(n);
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.encrypt((uint8_t *)output, (const uint8_t *)input, inputSize);
+ cipher.computeTag(((uint8_t *)output) + inputSize, 16);
+ ++n;
+ return inputSize + 16;
+}
+
+int NoiseCipherState_ChaChaPoly::decryptPacket
+ (void *output, size_t outputSize, const void *input, size_t inputSize)
+{
+ if (inputSize < 16 || outputSize < (inputSize - 16))
+ return -1;
+ uint64_t iv = htole64(n);
+ outputSize = inputSize - 16;
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.decrypt((uint8_t *)output, (const uint8_t *)input, outputSize);
+ if (cipher.checkTag(((const uint8_t *)input) + outputSize, 16)) {
+ ++n;
+ return outputSize;
+ }
+ memset(output, 0, outputSize); // Destroy the output if the tag is invalid.
+ return -1;
+}
+
+void NoiseCipherState_ChaChaPoly::rekey()
+{
+ uint8_t k[32];
+ uint64_t iv = 0xFFFFFFFFFFFFFFFFULL;
+ memset(k, 0, sizeof(k));
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.encrypt(k, k, sizeof(k));
+ cipher.setKey(k, sizeof(k));
+ clean(k);
+}
+
+void NoiseCipherState_ChaChaPoly::clear()
+{
+ cipher.clear();
+ n = 0;
+}
diff --git a/libraries/NoiseProtocol/src/NoiseCipherState_ChaChaPoly.h b/libraries/NoiseProtocol/src/NoiseCipherState_ChaChaPoly.h
new file mode 100644
index 00000000..b1ecb280
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseCipherState_ChaChaPoly.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_CIPHER_STATE_CHACHAPOLY_h
+#define NOISE_CIPHER_STATE_CHACHAPOLY_h
+
+#include "NoiseCipherState.h"
+#include "ChaChaPoly.h"
+
+class NoiseCipherState_ChaChaPoly : public NoiseCipherState
+{
+public:
+ explicit NoiseCipherState_ChaChaPoly(const uint8_t key[32]);
+ virtual ~NoiseCipherState_ChaChaPoly();
+
+ void setNonce(uint64_t nonce);
+
+ int encryptPacket
+ (void *output, size_t outputSize,
+ const void *input, size_t inputSize);
+ int decryptPacket
+ (void *output, size_t outputSize,
+ const void *input, size_t inputSize);
+
+ void rekey();
+
+ void clear();
+
+private:
+ ChaChaPoly cipher;
+ uint64_t n;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseDHState.cpp b/libraries/NoiseProtocol/src/NoiseDHState.cpp
new file mode 100644
index 00000000..a2466a25
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseDHState.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseDHState.h"
+#include
+
+/**
+ * \class NoiseDHState NoiseDHState.h
+ * \brief Abstract base class for Diffie-Hellman (DH) algorithms for Noise.
+ *
+ * This API defines how NoiseHandshakeState interacts with the DH
+ * algorithm to set local keys, query remote keys, generate ephemeral
+ * key pairs, etc. Subclasses implement specific DH algorithms, such as
+ * NoiseDHState_Curve25519.
+ */
+
+/**
+ * \fn NoiseDHState::NoiseDHState()
+ * \brief Constructs a new DH state object.
+ */
+
+/**
+ * \brief Destroys this DH state object.
+ */
+NoiseDHState::~NoiseDHState()
+{
+}
+
+/**
+ * \fn bool NoiseDHState::setParameter(Noise::Parameter id, const void *value, size_t size)
+ * \brief Sets a parameter on the DH object.
+ *
+ * \param id Identifies the parameter.
+ * \param value Points to the value to set for the parameter.
+ * \param size Size of the parameter value in bytes.
+ *
+ * \return Returns true if the parameter is set; false if the parameter
+ * \a id is not supported by the DH object; or false if the \a size is
+ * not valid for the parameter.
+ *
+ * If the \a id is for the private key component of a key pair, then the
+ * public key component will be generated from \a value. Returns false if
+ * it is not possible to generate the public key component from the
+ * private key component.
+ *
+ * \sa getParameter(), getParameterSize()
+ */
+
+/**
+ * \fn size_t NoiseDHState::getParameter(Noise::Parameter id, void *value, size_t maxSize) const
+ * \brief Gets the value associated with a parameter on the DH object.
+ *
+ * \param id Identifies the parameter.
+ * \param value Points to the buffer to write the parameter value to.
+ * \param maxSize Maximum size of the \a value buffer in bytes.
+ *
+ * \return The number of bytes that were written to \a value.
+ * \return 0 if \a id is not supported by the DH object.
+ * \return 0 if \a maxSize is not large enough to hold the parameter value.
+ * \return 0 if the parameter \a id has not been set yet.
+ *
+ * The getParameterSize() function can be used to determine the actual
+ * size of the parameter so that the caller can allocate a buffer large
+ * enough to contain it ahead of time.
+ *
+ * \sa setParameter(), getParameterSize()
+ */
+
+/**
+ * \fn size_t NoiseDHState::getParameterSize(Noise::Parameter id) const
+ * \brief Gets the size of a parameter on the DH object.
+ *
+ * \param id Identifies the parameter.
+ *
+ * \return The parameter's size, or zero if \a id is not valid for
+ * the DH object.
+ *
+ * If the parameter is variable-length, then this function will return
+ * the actual length of the value, which may be zero if the value has
+ * not been set yet.
+ *
+ * \sa getParameter(), setParameter(), hasParameter()
+ */
+
+/**
+ * \fn bool NoiseDHState::hasParameter(Noise::Parameter id) const
+ * \brief Determine if a parameter on this DH object has a value set.
+ *
+ * \param id Identifies the parameter.
+ *
+ * \return Returns true if \a id has a value; false if \a id does not
+ * have a value; false if \a id is not valid for the DH object.
+ *
+ * \sa getParameterSize(), getParameter(), removeParameter()
+ */
+
+/**
+ * \fn void NoiseDHState::removeParameter(Noise::Parameter id)
+ * \brief Removes a parameter from this DH object.
+ *
+ * \param id Identifies the parameter. If the parameter is unknown
+ * to the DH object, the request will be ignored.
+ *
+ * \sa hasParameter()
+ */
+
+/**
+ * \fn bool NoiseDHState::hashPublicKey(NoiseSymmetricState *sym, Noise::Parameter id)
+ * \brief Hashes a public key into the symmetric state.
+ *
+ * \param sym Symmetric state to hash the public key into.
+ * \param id Identifies the public key to hash.
+ *
+ * \return Returns true if the key was hashed; false if \a id is not supported
+ * by the DH object the \a id does not have a value at present.
+ */
+
+/**
+ * \fn size_t NoiseDHState::sharedKeySize() const
+ * \brief Gets the size of the shared keys that will be generated by
+ * ee(), es(), se(), and ss().
+ *
+ * \return The size of the shared keys in bytes.
+ *
+ * \sa ee(), es(), se(), ss()
+ */
+
+/**
+ * \fn void NoiseDHState::generateLocalEphemeralKeyPair()
+ * \brief Generates the local ephemeral key pair during a handshake.
+ *
+ * For testing purposes, the application can use setParameterKeyPair()
+ * to specify an ephemeral key after NoiseHandshakeState::start() and
+ * before this function is called. This permits testing with fixed
+ * key values. This functionality should not be used in real applications.
+ */
+
+/**
+ * \fn void NoiseDHState::ee(uint8_t *sharedKey)
+ * \brief Performs a DH operation using the local and remote ephemeral keys.
+ *
+ * \param sharedKey Returns the shared key. The buffer must be at least
+ * sharedKeySize() bytes in size.
+ *
+ * It is assumed that the caller has already verified that the DH object
+ * has all of the required keys before invoking this function.
+ *
+ * \sa es(), se(), ss()
+ */
+
+/**
+ * \fn void NoiseDHState::es(uint8_t *sharedKey)
+ * \brief Performs a DH operation using the local ephemeral key and the
+ * remote static key.
+ *
+ * \param sharedKey Returns the shared key. The buffer must be at least
+ * sharedKeySize() bytes in size.
+ *
+ * It is assumed that the caller has already verified that the DH object
+ * has all of the required keys before invoking this function.
+ *
+ * \sa ee(), se(), ss()
+ */
+
+/**
+ * \fn void NoiseDHState::se(uint8_t *sharedKey)
+ * \brief Performs a DH operation using the local static key and the
+ * remote ephemeral key.
+ *
+ * \param sharedKey Returns the shared key. The buffer must be at least
+ * sharedKeySize() bytes in size.
+ *
+ * It is assumed that the caller has already verified that the DH object
+ * has all of the required keys before invoking this function.
+ *
+ * \sa ee(), es(), ss()
+ */
+
+/**
+ * \fn void NoiseDHState::ss(uint8_t *sharedKey)
+ * \brief Performs a DH operation using the local and remote static keys.
+ *
+ * \param sharedKey Returns the shared key. The buffer must be at least
+ * sharedKeySize() bytes in size.
+ *
+ * It is assumed that the caller has already verified that the DH object
+ * has all of the required keys before invoking this function.
+ *
+ * \sa es(), se(), ss()
+ */
+
+/**
+ * \fn bool NoiseDHState::fallback(Noise::Party, const NoiseDHState *from)
+ * \brief Copies parameters from another DH object to perform a fallback.
+ *
+ * \param party The party to the new fallback handshake, Noise::Initiator
+ * or Noise::Responder.
+ * \param from DH object for the previous failed handshake.
+ *
+ * \return Returns false if there are insufficient parameters in \a from
+ * to perform a fallback or the DH algorithms do not match. Returns true
+ * if fallback is possible.
+ *
+ * This function copies the initiator's ephemeral keys and the local
+ * static key pair from a failed handshake into this DH object to
+ * initialize the new handshake.
+ */
+
+/**
+ * \fn void NoiseDHState::clear()
+ * \brief Clears all sensitive data from this object.
+ */
+
+/**
+ * \brief Helper function for copying a key value into the DH object.
+ *
+ * \param output Output buffer to copy the key into.
+ * \param expectedSize Expected size of the key value in bytes.
+ * \param value Points to the input value to be stored.
+ * \param size Size of the input value in bytes.
+ *
+ * \return Returns true if the value is stored, or false if \a size is
+ * not the same as \a expectedSize or \a value is NULL.
+ *
+ * \sa copyParameterOut()
+ */
+bool NoiseDHState::copyParameterIn
+ (void *output, size_t expectedSize, const void *value, size_t size)
+{
+ if (size != expectedSize || !value)
+ return false;
+ memcpy(output, value, size);
+ return true;
+}
+
+/**
+ * \brief Helper function for copying a key value out of the DH object.
+ *
+ * \param output Output buffer to copy the key into.
+ * \param maxOutput Maximum size of the output buffer in bytes.
+ * \param value Points to input key value to be copied.
+ * \param size Size of the input key value.
+ *
+ * \return The actual size of the copied key value if it fits within
+ * \a maxOutputBytes. Returns zero if \a size is greater than \a maxOutput
+ * or \a output is NULL.
+ *
+ * \sa copyParameterIn()
+ */
+size_t NoiseDHState::copyParameterOut
+ (void *output, size_t maxOutput, const void *value, size_t size)
+{
+ if (size > maxOutput || !output)
+ return 0;
+ memcpy(output, value, size);
+ return size;
+}
diff --git a/libraries/NoiseProtocol/src/NoiseDHState.h b/libraries/NoiseProtocol/src/NoiseDHState.h
new file mode 100644
index 00000000..f139b4a5
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseDHState.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_DH_STATE_h
+#define NOISE_DH_STATE_h
+
+#include "NoiseNamespace.h"
+#include
+#include
+
+class NoiseSymmetricState;
+
+class NoiseDHState
+{
+public:
+ NoiseDHState() {}
+ virtual ~NoiseDHState();
+
+ virtual bool setParameter
+ (Noise::Parameter id, const void *value, size_t size) = 0;
+ virtual size_t getParameter
+ (Noise::Parameter id, void *value, size_t maxSize) const = 0;
+ virtual size_t getParameterSize(Noise::Parameter id) const = 0;
+ virtual bool hasParameter(Noise::Parameter id) const = 0;
+ virtual void removeParameter(Noise::Parameter id) = 0;
+
+ virtual bool hashPublicKey
+ (NoiseSymmetricState *sym, Noise::Parameter id) = 0;
+
+ virtual size_t sharedKeySize() const = 0;
+
+ virtual void generateLocalEphemeralKeyPair() = 0;
+
+ virtual void ee(uint8_t *sharedKey) = 0;
+ virtual void es(uint8_t *sharedKey) = 0;
+ virtual void se(uint8_t *sharedKey) = 0;
+ virtual void ss(uint8_t *sharedKey) = 0;
+
+ virtual bool fallback(Noise::Party party, const NoiseDHState *from) = 0;
+
+ virtual void clear() = 0;
+
+protected:
+ static bool copyParameterIn
+ (void *output, size_t expectedSize, const void *value, size_t size);
+ static size_t copyParameterOut
+ (void *output, size_t maxOutput, const void *value, size_t size);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseDHState_Curve25519.cpp b/libraries/NoiseProtocol/src/NoiseDHState_Curve25519.cpp
new file mode 100644
index 00000000..360f1485
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseDHState_Curve25519.cpp
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseDHState_Curve25519.h"
+#include "NoiseSymmetricState.h"
+#include "Curve25519.h"
+#include "Crypto.h"
+#include "RNG.h"
+#include
+
+/**
+ * \class NoiseDHState_Curve25519 NoiseDHState_Curve25519.h
+ * \brief Noise protocol interface to the Curve25519 algorithm.
+ */
+
+/**
+ * \class NoiseDHState_Curve25519_EphemOnly NoiseDHState_Curve25519.h
+ * \brief Noise protocol interface to the ephemeral-only Curve25519 algorithm.
+ *
+ * This class is intended for use with the "NN" pattern which does not
+ * require static keys. It saves 96 bytes of memory compared with
+ * NoiseDHState_Curve25519.
+ */
+
+#define HAVE_25519_LOCAL_EPHEM_PUBLIC 0x01
+#define HAVE_25519_LOCAL_EPHEM_PRIVATE 0x02
+#define HAVE_25519_LOCAL_STATIC_PUBLIC 0x04
+#define HAVE_25519_LOCAL_STATIC_PRIVATE 0x08
+#define HAVE_25519_REMOTE_EPHEM_PUBLIC 0x10
+#define HAVE_25519_REMOTE_STATIC_PUBLIC 0x20
+
+/**
+ * \brief Constructs a new ephemeral-only Curve25519 DH object.
+ */
+NoiseDHState_Curve25519_EphemOnly::NoiseDHState_Curve25519_EphemOnly()
+{
+ memset(&st, 0, sizeof(st));
+}
+
+/**
+ * \brief Destroys this ephemeral-only Curve25519 DH object.
+ */
+NoiseDHState_Curve25519_EphemOnly::~NoiseDHState_Curve25519_EphemOnly()
+{
+ clean(st);
+}
+
+bool NoiseDHState_Curve25519_EphemOnly::setParameter
+ (Noise::Parameter id, const void *value, size_t size)
+{
+ switch (id) {
+ case Noise::LocalEphemPrivateKey:
+ case Noise::LocalEphem25519PrivateKey:
+ if (!copyParameterIn(st.le, sizeof(st.le), value, size))
+ break;
+ st.le[0] &= 0xF8;
+ st.le[31] = (st.le[31] & 0x7F) | 0x40;
+ Curve25519::eval(st.lf, st.le, 0);
+ st.flags |= HAVE_25519_LOCAL_EPHEM_PRIVATE |
+ HAVE_25519_LOCAL_EPHEM_PUBLIC;
+ return true;
+ case Noise::LocalEphemKeyPair:
+ case Noise::LocalEphem25519KeyPair:
+ if (size != 64)
+ break;
+ if (!copyParameterIn(st.le, sizeof(st.le), value, 32))
+ break;
+ if (!copyParameterIn
+ (st.lf, sizeof(st.lf), ((const uint8_t *)value) + 32, 32))
+ break;
+ st.flags |= HAVE_25519_LOCAL_EPHEM_PRIVATE |
+ HAVE_25519_LOCAL_EPHEM_PUBLIC;
+ return true;
+ case Noise::RemoteEphemPublicKey:
+ case Noise::RemoteEphem25519PublicKey:
+ if (!copyParameterIn(st.re, sizeof(st.re), value, size))
+ break;
+ st.flags |= HAVE_25519_REMOTE_EPHEM_PUBLIC;
+ return true;
+ default: break;
+ }
+ return false;
+}
+
+size_t NoiseDHState_Curve25519_EphemOnly::getParameter
+ (Noise::Parameter id, void *value, size_t maxSize) const
+{
+ switch (id) {
+ case Noise::LocalEphemPrivateKey:
+ case Noise::LocalEphem25519PrivateKey:
+ if (!(st.flags & HAVE_25519_LOCAL_EPHEM_PRIVATE))
+ break;
+ return copyParameterOut(value, maxSize, st.le, sizeof(st.le));
+ case Noise::LocalEphemPublicKey:
+ case Noise::LocalEphem25519PublicKey:
+ if (!(st.flags & HAVE_25519_LOCAL_EPHEM_PUBLIC))
+ break;
+ return copyParameterOut(value, maxSize, st.lf, sizeof(st.lf));
+ case Noise::LocalEphemKeyPair:
+ case Noise::LocalEphem25519KeyPair:
+ if (!(st.flags & HAVE_25519_LOCAL_EPHEM_PRIVATE))
+ break;
+ if (maxSize < 64)
+ break;
+ if (copyParameterOut(value, 32, st.le, sizeof(st.le)) != 32)
+ break;
+ if (copyParameterOut
+ (((uint8_t *)value) + 32, 32, st.lf, sizeof(st.lf)) != 32)
+ break;
+ return 64;
+ case Noise::RemoteEphemPublicKey:
+ case Noise::RemoteEphem25519PublicKey:
+ if (!(st.flags & HAVE_25519_REMOTE_EPHEM_PUBLIC))
+ break;
+ return copyParameterOut(value, maxSize, st.re, sizeof(st.re));
+ default: break;
+ }
+ return 0;
+}
+
+size_t NoiseDHState_Curve25519_EphemOnly::getParameterSize(Noise::Parameter id) const
+{
+ switch (id) {
+ case Noise::LocalEphemKeyPair:
+ case Noise::LocalEphem25519KeyPair:
+ return 64;
+
+ case Noise::LocalEphemPrivateKey:
+ case Noise::LocalEphem25519PrivateKey:
+ case Noise::LocalEphemPublicKey:
+ case Noise::LocalEphem25519PublicKey:
+ case Noise::RemoteEphemPublicKey:
+ case Noise::RemoteEphem25519PublicKey:
+ return 32;
+
+ default:
+ return 0;
+ }
+}
+
+bool NoiseDHState_Curve25519_EphemOnly::hasParameter(Noise::Parameter id) const
+{
+ switch (id) {
+ case Noise::LocalEphemKeyPair:
+ case Noise::LocalEphemPrivateKey:
+ case Noise::LocalEphem25519KeyPair:
+ case Noise::LocalEphem25519PrivateKey:
+ return (st.flags & HAVE_25519_LOCAL_EPHEM_PRIVATE) != 0;
+ case Noise::LocalEphemPublicKey:
+ case Noise::LocalEphem25519PublicKey:
+ return (st.flags & HAVE_25519_LOCAL_EPHEM_PUBLIC) != 0;
+ case Noise::RemoteEphemPublicKey:
+ case Noise::RemoteEphem25519PublicKey:
+ return (st.flags & HAVE_25519_REMOTE_EPHEM_PUBLIC) != 0;
+ default: break;
+ }
+ return false;
+}
+
+void NoiseDHState_Curve25519_EphemOnly::removeParameter(Noise::Parameter id)
+{
+ switch (id) {
+ case Noise::LocalEphemKeyPair:
+ case Noise::LocalEphemPrivateKey:
+ case Noise::LocalEphemPublicKey:
+ case Noise::LocalEphem25519KeyPair:
+ case Noise::LocalEphem25519PrivateKey:
+ case Noise::LocalEphem25519PublicKey:
+ st.flags &= ~(HAVE_25519_LOCAL_EPHEM_PRIVATE |
+ HAVE_25519_LOCAL_EPHEM_PUBLIC);
+ break;
+
+ case Noise::RemoteEphemPublicKey:
+ case Noise::RemoteEphem25519PublicKey:
+ st.flags &= ~HAVE_25519_REMOTE_EPHEM_PUBLIC;
+ break;
+
+ default: break;
+ }
+}
+
+bool NoiseDHState_Curve25519_EphemOnly::hashPublicKey
+ (NoiseSymmetricState *sym, Noise::Parameter id)
+{
+ switch (id) {
+ case Noise::LocalEphemPublicKey:
+ case Noise::LocalEphem25519PublicKey:
+ if (!(st.flags & HAVE_25519_LOCAL_EPHEM_PUBLIC))
+ break;
+ sym->mixHash(st.lf, sizeof(st.lf));
+ return true;
+ case Noise::RemoteEphemPublicKey:
+ case Noise::RemoteEphem25519PublicKey:
+ if (!(st.flags & HAVE_25519_REMOTE_EPHEM_PUBLIC))
+ break;
+ sym->mixHash(st.re, sizeof(st.re));
+ return true;
+ default: break;
+ }
+ return false;
+}
+
+size_t NoiseDHState_Curve25519_EphemOnly::sharedKeySize() const
+{
+ return 32;
+}
+
+void NoiseDHState_Curve25519_EphemOnly::generateLocalEphemeralKeyPair()
+{
+ // For testing, the ephemeral key pair can be provided ahead of
+ // time by the test harness. Only create a new pair if we need it.
+ if (!(st.flags & HAVE_25519_LOCAL_EPHEM_PRIVATE)) {
+ RNG.rand(st.le, 32);
+ st.le[0] &= 0xF8;
+ st.le[31] = (st.le[31] & 0x7F) | 0x40;
+ Curve25519::eval(st.lf, st.le, 0);
+ }
+}
+
+void NoiseDHState_Curve25519_EphemOnly::ee(uint8_t *sharedKey)
+{
+ Curve25519::eval(sharedKey, st.le, st.re);
+}
+
+// es(), se(), and ss() shouldn't be called for ephemeral-only
+// handshakes so we simply stub them out. If they are called
+// by accident then zeroing the sharedKey ensures that we don't
+// accidentally leak information about previous memory contents.
+
+void NoiseDHState_Curve25519_EphemOnly::es(uint8_t *sharedKey)
+{
+ memset(sharedKey, 0, 32);
+}
+
+void NoiseDHState_Curve25519_EphemOnly::se(uint8_t *sharedKey)
+{
+ memset(sharedKey, 0, 32);
+}
+
+void NoiseDHState_Curve25519_EphemOnly::ss(uint8_t *sharedKey)
+{
+ memset(sharedKey, 0, 32);
+}
+
+bool NoiseDHState_Curve25519_EphemOnly::fallback
+ (Noise::Party party, const NoiseDHState *from)
+{
+ // Copy the initiator's ephemeral key into this object.
+ st.flags &= ~(HAVE_25519_LOCAL_EPHEM_PUBLIC |
+ HAVE_25519_LOCAL_EPHEM_PRIVATE |
+ HAVE_25519_REMOTE_EPHEM_PUBLIC);
+ if (party == Noise::Initiator) {
+ if (from->getParameter(Noise::LocalEphem25519PrivateKey, st.le, 32) != 32)
+ return false;
+ if (from->getParameter(Noise::LocalEphem25519PublicKey, st.lf, 32) != 32)
+ return false;
+ st.flags |= HAVE_25519_LOCAL_EPHEM_PUBLIC |
+ HAVE_25519_LOCAL_EPHEM_PRIVATE;
+ } else {
+ if (from->getParameter(Noise::RemoteEphem25519PublicKey, st.re, 32) != 32)
+ return false;
+ st.flags |= HAVE_25519_REMOTE_EPHEM_PUBLIC;
+ }
+ return true;
+}
+
+void NoiseDHState_Curve25519_EphemOnly::clear()
+{
+ clean(st);
+}
+
+/**
+ * \brief Constructs a new Curve25519 DH object.
+ */
+NoiseDHState_Curve25519::NoiseDHState_Curve25519()
+{
+ memset(&st2, 0, sizeof(st2));
+}
+
+/**
+ * \brief Destroys this Curve25519 DH object.
+ */
+NoiseDHState_Curve25519::~NoiseDHState_Curve25519()
+{
+ clean(st2);
+}
+
+bool NoiseDHState_Curve25519::setParameter
+ (Noise::Parameter id, const void *value, size_t size)
+{
+ switch (id) {
+ case Noise::LocalStaticPrivateKey:
+ case Noise::LocalStatic25519PrivateKey:
+ if (!copyParameterIn(st2.ls, sizeof(st2.ls), value, size))
+ break;
+ st2.ls[0] &= 0xF8;
+ st2.ls[31] = (st2.ls[31] & 0x7F) | 0x40;
+ Curve25519::eval(st2.lp, st2.ls, 0);
+ st.flags |= HAVE_25519_LOCAL_STATIC_PRIVATE |
+ HAVE_25519_LOCAL_STATIC_PUBLIC;
+ return true;
+ case Noise::LocalStaticKeyPair:
+ case Noise::LocalStatic25519KeyPair:
+ if (size != 64)
+ break;
+ if (!copyParameterIn(st2.ls, sizeof(st2.ls), value, 32))
+ break;
+ if (!copyParameterIn
+ (st2.lp, sizeof(st2.lp), ((const uint8_t *)value) + 32, 32))
+ break;
+ st.flags |= HAVE_25519_LOCAL_STATIC_PRIVATE |
+ HAVE_25519_LOCAL_STATIC_PUBLIC;
+ return true;
+ case Noise::RemoteStaticPublicKey:
+ case Noise::RemoteStatic25519PublicKey:
+ if (!copyParameterIn(st2.rs, sizeof(st2.rs), value, size))
+ break;
+ st.flags |= HAVE_25519_REMOTE_STATIC_PUBLIC;
+ return true;
+ default:
+ return NoiseDHState_Curve25519_EphemOnly::setParameter(id, value, size);
+ }
+ return false;
+}
+
+size_t NoiseDHState_Curve25519::getParameter
+ (Noise::Parameter id, void *value, size_t maxSize) const
+{
+ switch (id) {
+ case Noise::LocalStaticPrivateKey:
+ case Noise::LocalStatic25519PrivateKey:
+ if (!(st.flags & HAVE_25519_LOCAL_STATIC_PRIVATE))
+ break;
+ return copyParameterOut(value, maxSize, st2.ls, sizeof(st2.ls));
+ case Noise::LocalStaticPublicKey:
+ case Noise::LocalStatic25519PublicKey:
+ if (!(st.flags & HAVE_25519_LOCAL_STATIC_PUBLIC))
+ break;
+ return copyParameterOut(value, maxSize, st2.lp, sizeof(st2.lp));
+ case Noise::LocalStaticKeyPair:
+ case Noise::LocalStatic25519KeyPair:
+ if (!(st.flags & HAVE_25519_LOCAL_STATIC_PRIVATE))
+ break;
+ if (maxSize < 64)
+ break;
+ if (copyParameterOut(value, 32, st2.ls, sizeof(st2.ls)) != 32)
+ break;
+ if (copyParameterOut
+ (((uint8_t *)value) + 32, 32, st2.lp, sizeof(st2.lp)) != 32)
+ break;
+ return 64;
+ case Noise::RemoteStaticPublicKey:
+ case Noise::RemoteStatic25519PublicKey:
+ if (!(st.flags & HAVE_25519_REMOTE_STATIC_PUBLIC))
+ break;
+ return copyParameterOut(value, maxSize, st2.rs, sizeof(st2.rs));
+ default:
+ return NoiseDHState_Curve25519_EphemOnly::getParameter
+ (id, value, maxSize);
+ }
+ return 0;
+}
+
+size_t NoiseDHState_Curve25519::getParameterSize(Noise::Parameter id) const
+{
+ switch (id) {
+ case Noise::LocalStaticKeyPair:
+ case Noise::LocalStatic25519KeyPair:
+ return 64;
+
+ case Noise::LocalStaticPrivateKey:
+ case Noise::LocalStatic25519PrivateKey:
+ case Noise::LocalStaticPublicKey:
+ case Noise::LocalStatic25519PublicKey:
+ case Noise::RemoteStaticPublicKey:
+ case Noise::RemoteStatic25519PublicKey:
+ return 32;
+
+ default:
+ return NoiseDHState_Curve25519_EphemOnly::getParameterSize(id);
+ }
+}
+
+bool NoiseDHState_Curve25519::hasParameter(Noise::Parameter id) const
+{
+ switch (id) {
+ case Noise::LocalStaticKeyPair:
+ case Noise::LocalStaticPrivateKey:
+ case Noise::LocalStatic25519KeyPair:
+ case Noise::LocalStatic25519PrivateKey:
+ return (st.flags & HAVE_25519_LOCAL_STATIC_PRIVATE) != 0;
+ case Noise::LocalStaticPublicKey:
+ case Noise::LocalStatic25519PublicKey:
+ return (st.flags & HAVE_25519_LOCAL_STATIC_PUBLIC) != 0;
+ case Noise::RemoteStaticPublicKey:
+ case Noise::RemoteStatic25519PublicKey:
+ return (st.flags & HAVE_25519_REMOTE_STATIC_PUBLIC) != 0;
+ default:
+ return NoiseDHState_Curve25519_EphemOnly::getParameterSize(id);
+ }
+ return false;
+}
+
+void NoiseDHState_Curve25519::removeParameter(Noise::Parameter id)
+{
+ switch (id) {
+ case Noise::LocalStaticKeyPair:
+ case Noise::LocalStaticPrivateKey:
+ case Noise::LocalStaticPublicKey:
+ case Noise::LocalStatic25519KeyPair:
+ case Noise::LocalStatic25519PrivateKey:
+ case Noise::LocalStatic25519PublicKey:
+ st.flags &= ~(HAVE_25519_LOCAL_STATIC_PRIVATE |
+ HAVE_25519_LOCAL_STATIC_PUBLIC);
+ break;
+
+ case Noise::RemoteStaticPublicKey:
+ case Noise::RemoteStatic25519PublicKey:
+ st.flags &= ~HAVE_25519_REMOTE_STATIC_PUBLIC;
+ break;
+
+ default:
+ NoiseDHState_Curve25519_EphemOnly::removeParameter(id);
+ break;
+ }
+}
+
+bool NoiseDHState_Curve25519::hashPublicKey
+ (NoiseSymmetricState *sym, Noise::Parameter id)
+{
+ switch (id) {
+ case Noise::LocalStaticPublicKey:
+ case Noise::LocalStatic25519PublicKey:
+ if (!(st.flags & HAVE_25519_LOCAL_STATIC_PUBLIC))
+ break;
+ sym->mixHash(st2.lp, sizeof(st2.lp));
+ return true;
+ case Noise::RemoteStaticPublicKey:
+ case Noise::RemoteStatic25519PublicKey:
+ if (!(st.flags & HAVE_25519_REMOTE_STATIC_PUBLIC))
+ break;
+ sym->mixHash(st.re, sizeof(st.re));
+ return true;
+ default:
+ return NoiseDHState_Curve25519_EphemOnly::hashPublicKey(sym, id);
+ }
+ return false;
+}
+
+void NoiseDHState_Curve25519::es(uint8_t *sharedKey)
+{
+ Curve25519::eval(sharedKey, st.le, st2.rs);
+}
+
+void NoiseDHState_Curve25519::se(uint8_t *sharedKey)
+{
+ Curve25519::eval(sharedKey, st2.ls, st.re);
+}
+
+void NoiseDHState_Curve25519::ss(uint8_t *sharedKey)
+{
+ Curve25519::eval(sharedKey, st2.ls, st2.rs);
+}
+
+bool NoiseDHState_Curve25519::fallback
+ (Noise::Party party, const NoiseDHState *from)
+{
+ // Copy the initiator's ephemeral key into this object.
+ if (!NoiseDHState_Curve25519_EphemOnly::fallback(party, from))
+ return false;
+
+ // Copy the local static Curve25519 key into this object.
+ // Don't do this if we already have a local static key because
+ // we may be changing to a new key for the fallback handshake.
+ if (!(st.flags & HAVE_25519_LOCAL_STATIC_PRIVATE)) {
+ if (from->getParameter(Noise::LocalStatic25519PrivateKey, st2.ls, 32) != 32)
+ return false;
+ if (from->getParameter(Noise::LocalStatic25519PublicKey, st2.lp, 32) != 32)
+ return false;
+ st.flags |= HAVE_25519_LOCAL_STATIC_PUBLIC |
+ HAVE_25519_LOCAL_STATIC_PRIVATE;
+ }
+ return true;
+}
+
+void NoiseDHState_Curve25519::clear()
+{
+ NoiseDHState_Curve25519_EphemOnly::clear();
+ clean(st2);
+}
diff --git a/libraries/NoiseProtocol/src/NoiseDHState_Curve25519.h b/libraries/NoiseProtocol/src/NoiseDHState_Curve25519.h
new file mode 100644
index 00000000..be0f0895
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseDHState_Curve25519.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_DH_STATE_CURVE25519_h
+#define NOISE_DH_STATE_CURVE25519_h
+
+#include "NoiseDHState.h"
+
+class NoiseDHState_Curve25519;
+
+class NoiseDHState_Curve25519_EphemOnly : public NoiseDHState
+{
+public:
+ NoiseDHState_Curve25519_EphemOnly();
+ virtual ~NoiseDHState_Curve25519_EphemOnly();
+
+ bool setParameter(Noise::Parameter id, const void *value, size_t size);
+ size_t getParameter(Noise::Parameter id, void *value, size_t maxSize) const;
+ size_t getParameterSize(Noise::Parameter id) const;
+ bool hasParameter(Noise::Parameter id) const;
+ void removeParameter(Noise::Parameter id);
+
+ bool hashPublicKey(NoiseSymmetricState *sym, Noise::Parameter id);
+
+ size_t sharedKeySize() const;
+
+ void generateLocalEphemeralKeyPair();
+
+ void ee(uint8_t *sharedKey);
+ void es(uint8_t *sharedKey);
+ void se(uint8_t *sharedKey);
+ void ss(uint8_t *sharedKey);
+
+ bool fallback(Noise::Party party, const NoiseDHState *from);
+
+ void clear();
+
+private:
+ struct {
+ uint8_t le[32]; // Local ephemeral private key.
+ uint8_t lf[32]; // Local ephemeral public key.
+ uint8_t re[32]; // Remote ephemeral public key.
+ uint8_t flags; // Indicates which keys are present.
+ } st;
+
+ friend class NoiseDHState_Curve25519;
+};
+
+class NoiseDHState_Curve25519 : public NoiseDHState_Curve25519_EphemOnly
+{
+public:
+ NoiseDHState_Curve25519();
+ virtual ~NoiseDHState_Curve25519();
+
+ bool setParameter(Noise::Parameter id, const void *value, size_t size);
+ size_t getParameter(Noise::Parameter id, void *value, size_t maxSize) const;
+ size_t getParameterSize(Noise::Parameter id) const;
+ bool hasParameter(Noise::Parameter id) const;
+ void removeParameter(Noise::Parameter id);
+
+ bool hashPublicKey(NoiseSymmetricState *sym, Noise::Parameter id);
+
+ void es(uint8_t *sharedKey);
+ void se(uint8_t *sharedKey);
+ void ss(uint8_t *sharedKey);
+
+ bool fallback(Noise::Party party, const NoiseDHState *from);
+
+ void clear();
+
+private:
+ struct {
+ uint8_t ls[32]; // Local static private key.
+ uint8_t lp[32]; // Local static public key.
+ uint8_t rs[32]; // Remote static public key.
+ } st2;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseHandshakeState.cpp b/libraries/NoiseProtocol/src/NoiseHandshakeState.cpp
new file mode 100644
index 00000000..7901fb7a
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseHandshakeState.cpp
@@ -0,0 +1,1003 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseHandshakeState.h"
+#include "Crypto.h"
+#include
+
+/**
+ * \class NoiseHandshakeState NoiseHandshakeState.h
+ * \brief Abstract base class for the handshake phase of Noise protocols.
+ *
+ * This class is abstract. Subclasses provide implementations of specific
+ * Noise patterns like "XX".
+ */
+
+/**
+ * \class NoiseHandshakeStatePSK NoiseHandshakeState.h
+ * \brief Abstract base class for the handshake phase of Noise protocols,
+ * when that handshake involves a pre-shared key.
+ *
+ * This class is abstract. Subclasses provide implementations of specific
+ * Noise patterns like "NNpsk0".
+ *
+ * When a PSK-using handshake is initialized, the Noise::PreSharedKey
+ * parameter must be set on the handshake using setParameter(). Otherwise
+ * the handshake will fail when the PSK is needed later. For example:
+ *
+ * \code
+ * uint8_t psk[32] = {...};
+ * Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s handshake;
+ * handshake.setParameter(Noise::PreSharedKey, psk, sizeof(psk));
+ * handshake.start(Noise::Initiator);
+ * \endcode
+ */
+
+/**
+ * \brief Constructs a new Noise handshake.
+ */
+NoiseHandshakeState::NoiseHandshakeState()
+ : sym(0)
+ , dh(0)
+ , protoName(0)
+ , pty(Noise::Initiator)
+ , st(Noise::Failed)
+ , msgnum(0)
+{
+}
+
+/**
+ * \brief Destroys this Noise handshake.
+ */
+NoiseHandshakeState::~NoiseHandshakeState()
+{
+}
+
+/**
+ * \brief Starts the handshake for the local party.
+ *
+ * \param party Noise::Initiator or Noise::Responder.
+ * to identity the local party.
+ * \param prologue Points to the prologue string, or NULL if no prologue.
+ * \param prologueLen Length of the prologue string, or 0 if no prologue.
+ *
+ * This function should be followed by calls to write() and read() to
+ * process the packets in the handshake. Once the handshake has completed,
+ * the application should call split() to obtain the cipher objects to use
+ * to encrypt and decrypt transport messages.
+ *
+ * \sa state(), write(), read(), split()
+ */
+void NoiseHandshakeState::start
+ (Noise::Party party, const void *prologue, size_t prologueLen)
+{
+ pty = party;
+ st = (party == Noise::Initiator) ? Noise::Write : Noise::Read;
+ msgnum = 0;
+ removeKeys();
+ symmetricState()->initialize(protoName);
+ symmetricState()->mixHash(prologue, prologueLen);
+}
+
+/**
+ * \brief Starts a fallback handshake for the local party.
+ *
+ * \param fallbackFrom The previous failed handshake from which certain
+ * parameters are copied to start the new handshake.
+ * \param party Noise::Initiator or Noise::Responder.
+ * to identity the local party.
+ * \param prologue Points to the prologue string, or NULL if no prologue.
+ * \param prologueLen Length of the prologue string, or 0 if no prologue.
+ *
+ * \return Returns true if the handshake started, false if there are
+ * insufficient parameters in \a fallbackFrom to start the new handshake,
+ * or false if the handshake coes not implement a fallback protocol.
+ *
+ * This function should be followed by calls to write() and read() to
+ * process the packets in the handshake. Once the handshake has completed,
+ * the application should call split() to obtain the cipher objects to use
+ * to encrypt and decrypt transport messages.
+ *
+ * \note The application must call this function instead of start() for
+ * fallback handshakes. Calling start() directly from the application
+ * will not start the handshake correctly.
+ */
+bool NoiseHandshakeState::startFallback
+ (const NoiseHandshakeState *fallbackFrom, Noise::Party party,
+ const void *prologue, size_t prologueLen)
+{
+ // Default implementation does not support fallback.
+ return false;
+}
+
+/**
+ * \fn Noise::Party NoiseHandshakeState::party() const
+ * \brief Gets the identity of this party to the handshake.
+ *
+ * \return Noise::Initiator or Noise::Responder.
+ */
+
+/**
+ * \fn Noise::HandshakeState NoiseHandshakeState::state() const
+ * \brief Gets the state of the handshake.
+ *
+ * \return Noise::Write if the handshake is still in progress and the next
+ * operation is write().
+ * \return Noise::Read if the handshake is still in progress and the next
+ * operation is read().
+ * \return Noise::Split if the handshake has completed and the next operation
+ * is split().
+ * \return Noise::Finished if the handshake has completed and split() has
+ * already been called.
+ * \return Noise::Failed if the handshake has failed or it was never started.
+ *
+ * \sa write(), read()
+ */
+
+/**
+ * \fn const char *NoiseHandshakeState::protocolName() const
+ * \brief Gets the full name of the Noise protocol that is implemented
+ * by this handshake object.
+ *
+ * \return The full name of the Noise protocol; for example
+ * "Noise_XX_25519_ChaChaPoly_BLAKE2s".
+ */
+
+/**
+ * \brief Sets a parameter on the handshake.
+ *
+ * \param id Identifies the parameter.
+ * \param value Points to the value to set for the parameter.
+ * \param size Size of the parameter value in bytes.
+ *
+ * \return Returns true if the parameter is set; false if the parameter
+ * \a id is not supported by the handshake; or false if the \a size is
+ * not valid for the parameter.
+ *
+ * If the \a id is for the private key component of a key pair, then the
+ * public key component will be generated from \a value. Returns false if
+ * it is not possible to generate the public key component from the
+ * private key component.
+ *
+ * \sa getParameter(), getParameterSize()
+ */
+bool NoiseHandshakeState::setParameter
+ (Noise::Parameter id, const void *value, size_t size)
+{
+ if (dh)
+ return dh->setParameter(id, value, size);
+ return false;
+}
+
+/**
+ * \brief Gets the value associated with a parameter on the handshake.
+ *
+ * \param id Identifies the parameter.
+ * \param value Points to the buffer to write the parameter value to.
+ * \param maxSize Maximum size of the \a value buffer in bytes.
+ *
+ * \return The number of bytes that were written to \a value.
+ * \return 0 if \a id is not supported by the handshake.
+ * \return 0 if \a maxSize is not large enough to hold the parameter value.
+ * \return 0 if the parameter \a id has not been set yet.
+ *
+ * The getParameterSize() function can be used to determine the actual
+ * size of the parameter so that the caller can allocate a buffer large
+ * enough to contain it ahead of time.
+ *
+ * \sa setParameter(), getParameterSize()
+ */
+size_t NoiseHandshakeState::getParameter
+ (Noise::Parameter id, void *value, size_t maxSize) const
+{
+ if (dh)
+ return dh->getParameter(id, value, maxSize);
+ return 0;
+}
+
+/**
+ * \brief Gets the size of a parameter on the handshake.
+ *
+ * \param id Identifies the parameter.
+ *
+ * \return The parameter's size, or zero if \a id is not valid for
+ * the handshake.
+ *
+ * If the parameter is variable-length, then this function will return
+ * the actual length of the value, which may be zero if the value has
+ * not been set yet.
+ *
+ * \sa getParameter(), setParameter(), hasParameter()
+ */
+size_t NoiseHandshakeState::getParameterSize(Noise::Parameter id) const
+{
+ if (dh)
+ return dh->getParameterSize(id);
+ return 0;
+}
+
+/**
+ * \brief Determine if a parameter on this handshake has a value set.
+ *
+ * \param id Identifies the parameter.
+ *
+ * \return Returns true if \a id has a value; false if \a id does not
+ * have a value; false if \a id is not valid for the handshake.
+ *
+ * \sa getParameterSize(), getParameter(), removeParameter()
+ */
+bool NoiseHandshakeState::hasParameter(Noise::Parameter id) const
+{
+ if (dh)
+ return dh->hasParameter(id);
+ return false;
+}
+
+/**
+ * \brief Removes a parameter from this handshake.
+ *
+ * \param id Identifies the parameter. If the parameter is unknown
+ * to the handshake, the request will be ignored.
+ *
+ * \sa hasParameter()
+ */
+void NoiseHandshakeState::removeParameter(Noise::Parameter id)
+{
+ if (dh)
+ dh->removeParameter(id);
+}
+
+/**
+ * \brief Formats the next handshake packet to be written to the transport.
+ *
+ * \param output Points to a buffer to receive the formatted handshake packet.
+ * \param maxOutputSize Maximum size of the \a output buffer in bytes.
+ * \param payload Points to the application-supplied payload to be encrypted
+ * and sent with the handshake packet. May be NULL for no payload.
+ * \param payloadSize Number of bytes of payload; zero if no payload.
+ *
+ * \return The number of bytes that were written to \a output if the
+ * return value is greater than or equal to zero.
+ * \return -1 if there is insufficient space in the \a output buffer for the
+ * full handshake packet, or the state() is not NoiseHandshakeState::Write.
+ *
+ * After this function returns successfully, the application should call
+ * state() to determine what operation to perform next: read() or split().
+ *
+ * \sa read(), split(), state()
+ */
+int NoiseHandshakeState::write
+ (void *output, size_t maxOutputSize,
+ const void *payload, size_t payloadSize)
+{
+ // Cannot write if the handshake is not in the correct state.
+ if (st != Noise::Write)
+ return -1;
+
+ // Form a packet structure for the output buffer.
+ Packet packet;
+ packet.data = (uint8_t *)output;
+ packet.posn = 0;
+ packet.size = maxOutputSize;
+ packet.error = false;
+ packet.done = false;
+
+ // Run the tokens for the handshake pattern and format the payload.
+ writeTokens(packet, msgnum);
+ writePayload(packet, payload, payloadSize);
+
+ // Move onto the next state.
+ if (packet.error) {
+ st = Noise::Failed;
+ return -1;
+ } else if (packet.done) {
+ st = Noise::Split;
+ return (int)packet.posn;
+ } else {
+ ++msgnum;
+ st = Noise::Read;
+ return (int)packet.posn;
+ }
+}
+
+/**
+ * \brief Reads the contents of the next handshake packet from the transport.
+ *
+ * \param payload Points to a buffer to receive the decrypted payload data.
+ * \param maxPayloadSize Maximum size of the \a payload buffer in bytes.
+ * \param input Points to the incoming handshake packet from the transport.
+ * \param inputSize Number of bytes in the incoming handshake packet.
+ *
+ * \return The number of bytes that were written to \a payload if the
+ * return value is greater than or equal to zero.
+ * \return -1 if there is insufficient space in the \a payload buffer for the
+ * full payload, the state() is not NoiseHandshakeState::Read, or an
+ * error occurred while decrypting the packet.
+ *
+ * After this function returns successfully, the application should call
+ * state() to determine what operation to perform next: write() or split().
+ *
+ * \sa write(), split(), state()
+ */
+int NoiseHandshakeState::read
+ (void *payload, size_t maxPayloadSize,
+ const void *input, size_t inputSize)
+{
+ // Cannot read if the handshake is not in the correct state.
+ if (st != Noise::Read)
+ return -1;
+
+ // Form a packet structure for the input buffer.
+ Packet packet;
+ packet.data = (uint8_t *)(const_cast(input));
+ packet.posn = 0;
+ packet.size = inputSize;
+ packet.error = false;
+ packet.done = false;
+
+ // Run the tokens for the handshake pattern and extract the payload.
+ readTokens(packet, msgnum);
+ size_t result = readPayload(packet, payload, maxPayloadSize);
+
+ // Move onto the next state.
+ if (packet.error) {
+ st = Noise::Failed;
+ return -1;
+ } else if (packet.done) {
+ st = Noise::Split;
+ return (int)result;
+ } else {
+ ++msgnum;
+ st = Noise::Write;
+ return (int)result;
+ }
+}
+
+/**
+ * \brief Splits cipher objects for the transport phase of the session out
+ * of this handshake state once the handshake ends.
+ *
+ * \param tx Returns a pointer to the cipher object to use to encrypt messages
+ * for transmission to the remote party.
+ * \param rx Returns a pointer to the cipher object to use to decrypt messages
+ * that were received from the remote party.
+ *
+ * \return Returns true if the cipher objects were split out, or false if
+ * state() is not NoiseHandshakeState::Split.
+ *
+ * If \a tx or \a rx are NULL, the the respective cipher object will not
+ * be created. This is useful for one-way patterns.
+ *
+ * The application is responsible for destroying the \a tx and \a rx
+ * objects when it no longer requires them.
+ *
+ * \sa write(), read(), getHandshakeHash()
+ */
+bool NoiseHandshakeState::split
+ (NoiseCipherState **tx, NoiseCipherState **rx)
+{
+ if (tx)
+ *tx = 0;
+ if (rx)
+ *rx = 0;
+ if (st != Noise::Split)
+ return false;
+ if (pty == Noise::Initiator)
+ symmetricState()->split(tx, rx);
+ else
+ symmetricState()->split(rx, tx);
+ st = Noise::Finished;
+ return true;
+}
+
+/**
+ * \brief Gets the handshake hash after the handshake completes.
+ *
+ * \param data Data buffer to fill with the handshake hash.
+ * \param size Size of the \a data buffer in bytes.
+ *
+ * \return Returns true if the handshake hash was copied to \a data,
+ * or false if the handshake has not completed yet.
+ *
+ * If \a size is less than the size of the symmetric state's hash,
+ * then the value will be truncated to the first \a size bytes.
+ * If \a size is greater, then the extra bytes will be filled with zeroes.
+ *
+ * This function can be called just before or after split(). If the
+ * handshake has not completed yet or it is has failed, then the hash
+ * value will be unavailable.
+ *
+ * \sa split()
+ */
+bool NoiseHandshakeState::getHandshakeHash(void *data, size_t size)
+{
+ if (st != Noise::Split && st != Noise::Finished) {
+ memset(data, 0, size);
+ return false;
+ }
+ symmetricState()->getHandshakeHash(data, size);
+ return true;
+}
+
+/**
+ * \brief Clears all sensitive data from this handshake object.
+ *
+ * The application will need to call start() again to begin a new handshake.
+ */
+void NoiseHandshakeState::clear()
+{
+ sym->clear();
+ dh->clear();
+ pty = Noise::Initiator;
+ st = Noise::Failed;
+ msgnum = 0;
+}
+
+/**
+ * \fn NoiseSymmetricState *NoiseHandshakeState::symmetricState() const
+ * \brief Gets the symmetric state associated with this handshake.
+ *
+ * \return A pointer to the symmetric state.
+ *
+ * \sa setSymmetricState()
+ */
+
+/**
+ * \fn void NoiseHandshakeState::setSymmetricState(NoiseSymmetricState *symState)
+ * \brief Sets the symmetric state for this handshake.
+ *
+ * \param symState A pointer to the symmetric state.
+ *
+ * This function must be called from a subclass constructor to initialize
+ * the handshake object properly before start() is called.
+ *
+ * \sa symmetricState()
+ */
+
+/**
+ * \fn NoiseDHState *NoiseHandshakeState::dhState() const
+ * \brief Gets the DH object for this handshake.
+ *
+ * \return A pointer to the DH object.
+ *
+ * \sa setDHState()
+ */
+
+/**
+ * \fn void NoiseHandshakeState::setDHState(NoiseDHState *dhState)
+ * \brief Sets the DH object for this handshake.
+ *
+ * \param dhState A pointer to the DH object.
+ *
+ * This function must be called from a subclass constructor to initialize
+ * the handshake object properly before start() is called.
+ *
+ * \sa dhState()
+ */
+
+/**
+ * \fn const NoiseDHState *NoiseHandshakeState::otherDHState(const NoiseHandshakeState *handshake)
+ * \brief Gets the DH object within another handshake.
+ *
+ * \param handshake The other handshake.
+ *
+ * \return A pointer to the DH object for \a handshake.
+ */
+
+/**
+ * \fn void NoiseHandshakeState::setProtocolName(const char *name)
+ * \brief Sets the protocol name for this handshake.
+ *
+ * \param name The full Noise protocol name.
+ *
+ * This function must be called from a subclass constructor to initialize
+ * the handshake object properly before start() is called.
+ *
+ * \sa protocolName()
+ */
+
+/**
+ * \brief Removes keys from the parameter list that need to be
+ * generated or discovered during the course of the handshake.
+ *
+ * The default implementation removes the local and remote ephemeral keys
+ * but leaves local and remote static keys alone. Subclasses may also
+ * remove the remote static key if it is expected to be discovered during
+ * the handshake.
+ */
+void NoiseHandshakeState::removeKeys()
+{
+ removeParameter(Noise::LocalEphemKeyPair);
+ removeParameter(Noise::RemoteEphemPublicKey);
+}
+
+/**
+ * \fn void NoiseHandshakeState::writeTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+ * \brief Runs the tokens for a handshake message in write mode.
+ *
+ * \param packet The packet to format based on the tokens.
+ * \param msgnum The message number within the handshake, 0 for the first
+ * message, 1 for the second, and so on.
+ */
+
+/**
+ * \fn void NoiseHandshakeState::readTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+ * \brief Runs the tokens for a handshake message in read mode.
+ *
+ * \param packet The packet to read based on the tokens.
+ * \param msgnum The message number within the handshake, 0 for the first
+ * message, 1 for the second, and so on.
+ */
+
+/**
+ * \brief Processes an "e" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * If there is not enough room in \a packet to hold the ephemeral public key,
+ * then the error flag will be set in \a packet.
+ *
+ * \sa read_e()
+ */
+void NoiseHandshakeState::write_e(NoiseHandshakeState::Packet &packet)
+{
+ size_t len = dhState()->getParameterSize(Noise::LocalEphemPublicKey);
+ if ((packet.size - packet.posn) >= len) {
+ dhState()->generateLocalEphemeralKeyPair();
+ dhState()->getParameter
+ (Noise::LocalEphemPublicKey, packet.data + packet.posn, len);
+ symmetricState()->mixHash(packet.data + packet.posn, len);
+ packet.posn += len;
+ } else {
+ packet.error = true;
+ }
+}
+
+/**
+ * \brief Processes a "s" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * If there is not enough room in \a packet to hold the static public key,
+ * then the error flag will be set in \a packet.
+ *
+ * \sa read_s()
+ */
+void NoiseHandshakeState::write_s(NoiseHandshakeState::Packet &packet)
+{
+ // Check that the application has supplied us with a local static key.
+ if (!dhState()->hasParameter(Noise::LocalStaticPublicKey)) {
+ packet.error = true;
+ return;
+ }
+
+ // Write the local static public key to the outgoing message.
+ size_t len = dhState()->getParameterSize(Noise::LocalStaticPublicKey);
+ if ((packet.size - packet.posn) >= len) {
+ dhState()->getParameter
+ (Noise::LocalStaticPublicKey, packet.data + packet.posn, len);
+ int size = symmetricState()->encryptAndHash
+ (packet.data + packet.posn, packet.size - packet.posn,
+ packet.data + packet.posn, len);
+ if (size > 0)
+ packet.posn += size;
+ else
+ packet.error = true;
+ } else {
+ packet.error = true;
+ }
+}
+
+/**
+ * \brief Processes an "ee" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * \sa read_ee()
+ */
+void NoiseHandshakeState::write_ee(NoiseHandshakeState::Packet &packet)
+{
+ size_t size = dhState()->sharedKeySize();
+ uint8_t shared[size];
+ dhState()->ee(shared);
+ symmetricState()->mixKey(shared, size);
+ clean(shared, size);
+}
+
+/**
+ * \brief Processes an "es" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * \sa read_es()
+ */
+void NoiseHandshakeState::write_es(NoiseHandshakeState::Packet &packet)
+{
+ if (!dhState()->hasParameter(Noise::RemoteStaticPublicKey)) {
+ // We don't have a remote static key. It probably should have
+ // been provided ahead of time when the handshake started.
+ packet.error = true;
+ return;
+ }
+ size_t size = dhState()->sharedKeySize();
+ uint8_t shared[size];
+ if (pty == Noise::Initiator)
+ dhState()->es(shared);
+ else
+ dhState()->se(shared);
+ symmetricState()->mixKey(shared, size);
+ clean(shared, size);
+}
+
+/**
+ * \brief Processes a "se" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * \sa read_se()
+ */
+void NoiseHandshakeState::write_se(NoiseHandshakeState::Packet &packet)
+{
+ if (!dhState()->hasParameter(Noise::LocalStaticPrivateKey)) {
+ // We don't have a local static key. It probably should have
+ // been provided ahead of time when the handshake started.
+ packet.error = true;
+ return;
+ }
+ size_t size = dhState()->sharedKeySize();
+ uint8_t shared[size];
+ if (pty == Noise::Initiator)
+ dhState()->se(shared);
+ else
+ dhState()->es(shared);
+ symmetricState()->mixKey(shared, size);
+ clean(shared, size);
+}
+
+/**
+ * \brief Processes a "ss" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * \sa read_ss()
+ */
+void NoiseHandshakeState::write_ss(NoiseHandshakeState::Packet &packet)
+{
+ if (!dhState()->hasParameter(Noise::LocalStaticPrivateKey) ||
+ !dhState()->hasParameter(Noise::RemoteStaticPublicKey)) {
+ // We don't have all required static keys. They probably should
+ // have been provided ahead of time when the handshake started.
+ packet.error = true;
+ return;
+ }
+ size_t size = dhState()->sharedKeySize();
+ uint8_t shared[size];
+ dhState()->ss(shared);
+ symmetricState()->mixKey(shared, size);
+ clean(shared, size);
+}
+
+/**
+ * \brief Processes an "e" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * If there is not enough data in \a packet to for a valid ephemeral public
+ * key, then the error flag will be set in \a packet.
+ *
+ * \sa write_e()
+ */
+void NoiseHandshakeState::read_e(NoiseHandshakeState::Packet &packet)
+{
+ size_t len = dhState()->getParameterSize(Noise::RemoteEphemPublicKey);
+ if ((packet.size - packet.posn) >= len) {
+ if (dhState()->setParameter
+ (Noise::RemoteEphemPublicKey, packet.data + packet.posn, len)) {
+ symmetricState()->mixHash(packet.data + packet.posn, len);
+ } else {
+ packet.error = true;
+ }
+ packet.posn += len;
+ } else {
+ packet.error = true;
+ }
+}
+
+/**
+ * \brief Processes a "s" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * If there is not enough data in \a packet to for a valid static public
+ * key, or the value failed to decrypt, then the error flag will be set
+ * in \a packet.
+ *
+ * \sa write_s()
+ */
+void NoiseHandshakeState::read_s(NoiseHandshakeState::Packet &packet)
+{
+ size_t len = dhState()->getParameterSize(Noise::RemoteStaticPublicKey);
+ size_t fullLen = len;
+ if (symmetricState()->hasKey())
+ fullLen += symmetricState()->macLen();
+ if ((packet.size - packet.posn) >= fullLen) {
+ uint8_t s[len];
+ int size = symmetricState()->decryptAndHash
+ (s, len, packet.data + packet.posn, fullLen);
+ if (size > 0) {
+ packet.posn += size;
+ if (!dhState()->setParameter(Noise::RemoteStaticPublicKey, s, len))
+ packet.error = true;
+ } else {
+ packet.error = true;
+ }
+ clean(s, len);
+ } else {
+ packet.error = true;
+ }
+}
+
+/**
+ * \fn void NoiseHandshakeState::read_ee(NoiseHandshakeState::Packet &packet)
+ * \brief Processes an "ee" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * This is a convenience function. The "ee" token has identical behaviour
+ * when both reading and writing.
+ *
+ * \sa write_ee()
+ */
+
+/**
+ * \fn void NoiseHandshakeState::read_es(NoiseHandshakeState::Packet &packet)
+ * \brief Processes an "es" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * This is a convenience function. The "es" token has identical behaviour
+ * when both reading and writing.
+ *
+ * \sa write_es()
+ */
+
+/**
+ * \fn void NoiseHandshakeState::read_se(NoiseHandshakeState::Packet &packet)
+ * \brief Processes a "se" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * This is a convenience function. The "se" token has identical behaviour
+ * when both reading and writing.
+ *
+ * \sa write_se()
+ */
+
+/**
+ * \fn void NoiseHandshakeState::read_ss(NoiseHandshakeState::Packet &packet)
+ * \brief Processes a "ss" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * This is a convenience function. The "ss" token has identical behaviour
+ * when both reading and writing.
+ *
+ * \sa write_ss()
+ */
+
+/**
+ * \fn void NoiseHandshakeState::setState(Noise::HandshakeState state)
+ * \brief Sets the state of this handshake.
+ *
+ * \param state The new state.
+ *
+ * This is intended for use in subclass implementations of start() when
+ * initializing the handshake.
+ *
+ * \sa state()
+ */
+
+/**
+ * \brief Writes a payload to a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ * \param data Points to the plaintext payload data to be written.
+ * \param size Number of bytes of plaintext payload to write.
+ *
+ * If there is not enough room in \a packet to hold the encrypted payload,
+ * then the error flag will be set in \a packet.
+ *
+ * \sa readPayload()
+ */
+void NoiseHandshakeState::writePayload(NoiseHandshakeState::Packet &packet,
+ const void *data, size_t size)
+{
+ int result = symmetricState()->encryptAndHash
+ (packet.data + packet.posn, packet.size - packet.posn,
+ (const uint8_t *)data, size);
+ if (result >= 0)
+ packet.posn += result;
+ else
+ packet.error = true;
+}
+
+/**
+ * \brief Reads a payload from a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ * \param data Points to the buffer to place the plaintext payload data into.
+ * \param maxSize Maximum number of bytes that can be written to \a data.
+ *
+ * \return Number of plaintext bytes that were written to the \a data buffer.
+ *
+ * If there is a problem decrypting the payload, or \a maxSize is not large
+ * enough, then 0 will be returned and the error flag will be set in \a packet.
+ *
+ * \sa writePayload()
+ */
+size_t NoiseHandshakeState::readPayload(NoiseHandshakeState::Packet &packet,
+ void *data, size_t maxSize)
+{
+ int result = symmetricState()->decryptAndHash
+ ((uint8_t *)data, maxSize,
+ packet.data + packet.posn, packet.size - packet.posn);
+ packet.posn = packet.size;
+ if (result >= 0)
+ return result;
+ packet.error = true;
+ return 0;
+}
+
+/**
+ * \brief Constructs a new PSK-using handshake.
+ */
+NoiseHandshakeStatePSK::NoiseHandshakeStatePSK()
+ : havePSK(false)
+{
+}
+
+/**
+ * \brief Destroys this PSK-using handshake.
+ */
+NoiseHandshakeStatePSK::~NoiseHandshakeStatePSK()
+{
+ clean(psk);
+}
+
+bool NoiseHandshakeStatePSK::setParameter
+ (Noise::Parameter id, const void *value, size_t size)
+{
+ if (id == Noise::PreSharedKey) {
+ if (!value || size != 32)
+ return false;
+ memcpy(psk, value, size);
+ havePSK = true;
+ return true;
+ } else {
+ return NoiseHandshakeState::setParameter(id, value, size);
+ }
+}
+
+size_t NoiseHandshakeStatePSK::getParameter
+ (Noise::Parameter id, void *value, size_t maxSize) const
+{
+ if (id == Noise::PreSharedKey) {
+ if (!havePSK || !value || maxSize < 32)
+ return 0;
+ memcpy(value, psk, 32);
+ return 32;
+ } else {
+ return NoiseHandshakeState::getParameter(id, value, maxSize);
+ }
+}
+
+size_t NoiseHandshakeStatePSK::getParameterSize(Noise::Parameter id) const
+{
+ if (id == Noise::PreSharedKey)
+ return 32;
+ else
+ return NoiseHandshakeState::getParameterSize(id);
+}
+
+bool NoiseHandshakeStatePSK::hasParameter(Noise::Parameter id) const
+{
+ if (id == Noise::PreSharedKey)
+ return havePSK;
+ else
+ return NoiseHandshakeState::hasParameter(id);
+}
+
+void NoiseHandshakeStatePSK::removeParameter(Noise::Parameter id)
+{
+ if (id == Noise::PreSharedKey)
+ havePSK = false;
+ else
+ NoiseHandshakeState::removeParameter(id);
+}
+
+void NoiseHandshakeStatePSK::clear()
+{
+ clean(psk);
+ havePSK = false;
+ NoiseHandshakeState::clear();
+}
+
+/**
+ * \brief Processes an "e" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * This overrides the base class implementation of write_e() to provide
+ * additional behaviour for handshakes that involve PSK values.
+ */
+void NoiseHandshakeStatePSK::write_e(NoiseHandshakeState::Packet &packet)
+{
+ NoiseHandshakeState::write_e(packet);
+ if (!packet.error) {
+ size_t len = dhState()->getParameterSize(Noise::LocalEphemPublicKey);
+ symmetricState()->mixKey(packet.data + packet.posn - len, len);
+ }
+}
+
+/**
+ * \brief Processes an "e" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * This overrides the base class implementation of read_e() to provide
+ * additional behaviour for handshakes that involve PSK values.
+ */
+void NoiseHandshakeStatePSK::read_e(NoiseHandshakeState::Packet &packet)
+{
+ NoiseHandshakeState::read_e(packet);
+ if (!packet.error) {
+ size_t len = dhState()->getParameterSize(Noise::RemoteEphemPublicKey);
+ symmetricState()->mixKey(packet.data + packet.posn - len, len);
+ }
+}
+
+/**
+ * \brief Processes a "psk" token when writing a handshake packet.
+ *
+ * \param packet The handshake packet that is being written.
+ *
+ * \sa read_psk()
+ */
+void NoiseHandshakeStatePSK::write_psk(NoiseHandshakeState::Packet &packet)
+{
+ if (havePSK)
+ symmetricState()->mixKeyAndHash(psk, 32);
+ else
+ packet.error = true;
+}
+
+/**
+ * \fn void NoiseHandshakeStatePSK::read_psk(NoiseHandshakeState::Packet &packet)
+ * \brief Processes a "psk" token when reading a handshake packet.
+ *
+ * \param packet The handshake packet that is being read.
+ *
+ * This is a convenience function. The "psk" token has identical behaviour
+ * when both reading and writing.
+ *
+ * \sa write_psk()
+ */
diff --git a/libraries/NoiseProtocol/src/NoiseHandshakeState.h b/libraries/NoiseProtocol/src/NoiseHandshakeState.h
new file mode 100644
index 00000000..0efdbaff
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseHandshakeState.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_HANDSHAKE_STATE_h
+#define NOISE_HANDSHAKE_STATE_h
+
+#include "NoiseNamespace.h"
+#include "NoiseSymmetricState.h"
+#include "NoiseDHState.h"
+#include "NoiseCipherState.h"
+
+class NoiseHandshakeState
+{
+public:
+ virtual ~NoiseHandshakeState();
+
+ virtual void start
+ (Noise::Party party, const void *prologue = 0, size_t prologueLen = 0);
+ virtual bool startFallback
+ (const NoiseHandshakeState *fallbackFrom, Noise::Party party,
+ const void *prologue = 0, size_t prologueLen = 0);
+
+ Noise::Party party() const { return pty; }
+ Noise::HandshakeState state() const { return st; }
+ const char *protocolName() const { return protoName; }
+
+ virtual bool setParameter
+ (Noise::Parameter id, const void *value, size_t size);
+ virtual size_t getParameter
+ (Noise::Parameter id, void *value, size_t maxSize) const;
+ virtual size_t getParameterSize(Noise::Parameter id) const;
+ virtual bool hasParameter(Noise::Parameter id) const;
+ virtual void removeParameter(Noise::Parameter id);
+
+ int write(void *output, size_t maxOutputSize,
+ const void *payload, size_t payloadSize);
+ int read(void *payload, size_t maxPayloadSize,
+ const void *input, size_t inputSize);
+ bool split(NoiseCipherState **tx, NoiseCipherState **rx);
+ bool getHandshakeHash(void *data, size_t size);
+
+ virtual void clear();
+
+protected:
+ NoiseHandshakeState();
+
+ NoiseSymmetricState *symmetricState() const { return sym; }
+ void setSymmetricState(NoiseSymmetricState *symState) { sym = symState; }
+
+ NoiseDHState *dhState() const { return dh; }
+ void setDHState(NoiseDHState *dhState) { dh = dhState; }
+
+ static const NoiseDHState *otherDHState
+ (const NoiseHandshakeState *handshake) { return handshake->dh; }
+
+ void setProtocolName(const char *name) { protoName = name; }
+
+ virtual void removeKeys();
+
+ /**
+ * \brief Information about a handshake packet that is being processed.
+ */
+ struct Packet
+ {
+ uint8_t *data; /**< Points to the start of the packet's data */
+ size_t posn; /**< Current processing position in the data array */
+ size_t size; /**< Maximum amount of available packet data */
+ bool error; /**< Set to true if an error has occurred */
+ bool done; /**< Set to true for the last handshake message */
+ };
+
+ virtual void writeTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum) = 0;
+ virtual void readTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum) = 0;
+
+ virtual void write_e(NoiseHandshakeState::Packet &packet);
+ void write_s(NoiseHandshakeState::Packet &packet);
+ void write_ee(NoiseHandshakeState::Packet &packet);
+ void write_es(NoiseHandshakeState::Packet &packet);
+ void write_se(NoiseHandshakeState::Packet &packet);
+ void write_ss(NoiseHandshakeState::Packet &packet);
+
+ virtual void read_e(NoiseHandshakeState::Packet &packet);
+ void read_s(NoiseHandshakeState::Packet &packet);
+ void read_ee(NoiseHandshakeState::Packet &packet) { write_ee(packet); }
+ void read_es(NoiseHandshakeState::Packet &packet) { write_es(packet); }
+ void read_se(NoiseHandshakeState::Packet &packet) { write_se(packet); }
+ void read_ss(NoiseHandshakeState::Packet &packet) { write_ss(packet); }
+
+ void setState(Noise::HandshakeState state) { st = state; }
+
+private:
+ NoiseSymmetricState *sym;
+ NoiseDHState *dh;
+ const char *protoName;
+ Noise::Party pty;
+ Noise::HandshakeState st;
+ uint8_t msgnum;
+
+ void writePayload(NoiseHandshakeState::Packet &packet,
+ const void *data, size_t size);
+ size_t readPayload(NoiseHandshakeState::Packet &packet,
+ void *data, size_t maxSize);
+};
+
+class NoiseHandshakeStatePSK : public NoiseHandshakeState
+{
+public:
+ virtual ~NoiseHandshakeStatePSK();
+
+ bool setParameter(Noise::Parameter id, const void *value, size_t size);
+ size_t getParameter(Noise::Parameter id, void *value, size_t maxSize) const;
+ size_t getParameterSize(Noise::Parameter id) const;
+ bool hasParameter(Noise::Parameter id) const;
+ void removeParameter(Noise::Parameter id);
+
+ void clear();
+
+protected:
+ NoiseHandshakeStatePSK();
+
+ void write_e(NoiseHandshakeState::Packet &packet);
+ void read_e(NoiseHandshakeState::Packet &packet);
+ void write_psk(NoiseHandshakeState::Packet &packet);
+ void read_psk(NoiseHandshakeState::Packet &packet) { write_psk(packet); }
+
+private:
+ uint8_t psk[32];
+ bool havePSK;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseNamespace.cpp b/libraries/NoiseProtocol/src/NoiseNamespace.cpp
new file mode 100644
index 00000000..505a4474
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseNamespace.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseNamespace.h"
+
+/**
+ * \namespace Noise
+ * \brief Common definitions for the Noise protocol.
+ */
diff --git a/libraries/NoiseProtocol/src/NoiseNamespace.h b/libraries/NoiseProtocol/src/NoiseNamespace.h
new file mode 100644
index 00000000..7985efe1
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseNamespace.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_NAMESPACE_h
+#define NOISE_NAMESPACE_h
+
+#include
+
+namespace Noise
+{
+ /**
+ * \brief Indicates which party is engaging in a handshake.
+ */
+ enum Party
+ {
+ Initiator, /**< Local party is the initiator of the handshake */
+ Responder /**< Local party is the responder of the handshake */
+ };
+
+ /**
+ * \brief Current state of a handshake.
+ */
+ enum HandshakeState
+ {
+ Write, /**< Next operation is a handshake packet write() */
+ Read, /**< Next operation is a handshake packet read() */
+ Split, /**< Handshake complete, next operation is split() */
+ Finished, /**< Handshake finished and split() already done */
+ Failed /**< Handshake has failed or was never started */
+ };
+
+ /**
+ * \brief Identifiers for handshake parameters.
+ */
+ enum Parameter
+ {
+ // Standard handshake parameters.
+ LocalStaticKeyPair = 1, /**< Local DH static key pair */
+ LocalStaticPrivateKey = 2, /**< Local DH static private key */
+ LocalStaticPublicKey = 3, /**< Local DH static public key */
+ RemoteStaticPublicKey = 4, /**< Remote DH static public key */
+ PreSharedKey = 5, /**< Pre-shared symmetric key */
+
+ // Specific algorithm names for meta-handshakes.
+ LocalStatic25519KeyPair = 100, /**< Local Curve25519 key pair */
+ LocalStatic25519PrivateKey = 101, /**< Local Curve25519 private key */
+ LocalStatic25519PublicKey = 102, /**< Local Curve25519 public key */
+ RemoteStatic25519PublicKey = 103, /**< Remote Curve25519 public key */
+
+ // Internal parameters (for application testing use only).
+ LocalEphemKeyPair = 200, /**< Local DH ephemeral key pair */
+ LocalEphemPrivateKey = 201, /**< Local DH ephemeral private key */
+ LocalEphemPublicKey = 202, /**< Local DH ephemeral public key */
+ RemoteEphemPublicKey = 203, /**< Remote DH ephemeral public key */
+ LocalEphem25519KeyPair = 204, /**< Local ephemeral Curve25519 key pair */
+ LocalEphem25519PrivateKey = 205, /**< Local ephemeral Curve25519 private key */
+ LocalEphem25519PublicKey = 206, /**< Local ephemeral Curve25519 public key */
+ RemoteEphem25519PublicKey = 207 /**< Remote ephemeral Curve25519 public key */
+ };
+
+}; // namespace Noise
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseProtocol.h b/libraries/NoiseProtocol/src/NoiseProtocol.h
new file mode 100644
index 00000000..7d3fd794
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseProtocol.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_PROTOCOL_h
+#define NOISE_PROTOCOL_h
+
+#include "NoiseNamespace.h"
+
+#include "Noise_IK_25519_AESGCM_SHA256.h"
+#include "Noise_IK_25519_ChaChaPoly_BLAKE2s.h"
+#include "Noise_IK_25519_ChaChaPoly_SHA256.h"
+
+#include "Noise_NNpsk0_25519_AESGCM_SHA256.h"
+#include "Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.h"
+#include "Noise_NNpsk0_25519_ChaChaPoly_SHA256.h"
+
+#include "Noise_Pipes_25519_AESGCM_SHA256.h"
+#include "Noise_Pipes_25519_ChaChaPoly_BLAKE2s.h"
+#include "Noise_Pipes_25519_ChaChaPoly_SHA256.h"
+
+#include "Noise_XX_25519_AESGCM_SHA256.h"
+#include "Noise_XX_25519_ChaChaPoly_BLAKE2s.h"
+#include "Noise_XX_25519_ChaChaPoly_SHA256.h"
+
+#include "Noise_XXfallback_25519_AESGCM_SHA256.h"
+#include "Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h"
+#include "Noise_XXfallback_25519_ChaChaPoly_SHA256.h"
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseProtocolDescriptor.cpp b/libraries/NoiseProtocol/src/NoiseProtocolDescriptor.cpp
new file mode 100644
index 00000000..83bf5b55
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseProtocolDescriptor.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseProtocolDescriptor.h"
+
+/**
+ * \class NoiseProtocolDescriptor NoiseProtocolDescriptor.h
+ * \brief Description of a Noise protocol and a method to create a handshake
+ * object that implements the protocol.
+ *
+ * This class is abstract. The caller should instantiate a subclass like
+ * Noise_XX_25519_ChaChaPoly_BLAKE2s or Noise_XX_25519_AESGCM_SHA256 to
+ * get an actual descriptor.
+ */
+
+/**
+ * \fn NoiseProtocolDescriptor::NoiseProtocolDescriptor(const char *name, const char *alias)
+ * \brief Creates a new Noise protocol descriptor.
+ *
+ * \param name Name of the Noise protocol, e.g. "Noise_XX_25519_AESGCM_SHA256".
+ * \param alias NoiseTinyLink alias for the Noise protocol; e.g. "1". Set this
+ * to NULL if the protocol does not have a NoiseTinyLink alias defined.
+ */
+
+/**
+ * \brief Destroys this Noise protocol descriptor.
+ */
+NoiseProtocolDescriptor::~NoiseProtocolDescriptor()
+{
+}
+
+/**
+ * \fn const char *NoiseProtocolDescriptor::protocolName() const
+ * \brief Gets the name of the Noise protocol represented by this descriptor.
+ *
+ * \return The name of the Noise protocol.
+ *
+ * \sa protocolAlias()
+ */
+
+/**
+ * \fn const char *NoiseProtocolDescriptor::protocolAlias() const
+ * \brief Gets the NoiseTinyLink alias for the Noise protocol represented
+ * by this descriptor.
+ *
+ * \return The alias or NULL if the protocol does not have a NoiseTinyLink
+ * alias defined.
+ *
+ * \sa protocolName()
+ */
+
+/**
+ * \fn NoiseHandshakeState *NoiseProtocolDescriptor::createHandshake() const
+ * \brief Creates a handshake object for the Noise protocol represented
+ * by this descriptor.
+ *
+ * \return A new handshake object for the protocol.
+ */
+
+/**
+ * \brief Returns the descriptor for the abbreviated protocol, if any.
+ *
+ * \return Returns a pointer to the abbreviated protocol descriptor, or NULL
+ * if this protocol does not have an abbreviated version.
+ *
+ * This function and fallbackDescriptor() to intended to help implement
+ * fallback-using protocols like Noise Pipes. In the case of Noise Pipes,
+ * the full protocol would be XX, the abbreviated protocol would be IK,
+ * and the fallback protocol would XXfallback.
+ *
+ * The abbreviated protocol should be selected if a remote static public
+ * key is available when the handshake starts. Otherwise the full protocol
+ * should be used to discover the remote static public key dynamically.
+ *
+ * \sa fallbackDescriptor()
+ */
+const NoiseProtocolDescriptor *NoiseProtocolDescriptor::abbreviatedDescriptor() const
+{
+ return 0;
+}
+
+/**
+ * \brief Returns the descriptor for the fallback protocol, if any.
+ *
+ * \return Returns a pointer to the fallback protocol descriptor, or NULL
+ * if it is not possible to fall back from the abbreviated protocol to
+ * another protocol. The default implementation returns NULL.
+ *
+ * \sa abbreviatedDescriptor()
+ */
+const NoiseProtocolDescriptor *NoiseProtocolDescriptor::fallbackDescriptor() const
+{
+ return 0;
+}
diff --git a/libraries/NoiseProtocol/src/NoiseProtocolDescriptor.h b/libraries/NoiseProtocol/src/NoiseProtocolDescriptor.h
new file mode 100644
index 00000000..32788fb7
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseProtocolDescriptor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_PROTOCOL_DESCRIPTOR_h
+#define NOISE_PROTOCOL_DESCRIPTOR_h
+
+class NoiseHandshakeState;
+
+class NoiseProtocolDescriptor
+{
+public:
+ virtual ~NoiseProtocolDescriptor();
+
+ const char *protocolName() const { return protoName; }
+ const char *protocolAlias() const { return protoAlias; }
+
+ virtual NoiseHandshakeState *createHandshake() const = 0;
+
+ virtual const NoiseProtocolDescriptor *abbreviatedDescriptor() const;
+ virtual const NoiseProtocolDescriptor *fallbackDescriptor() const;
+
+protected:
+ explicit NoiseProtocolDescriptor(const char *name, const char *alias = 0)
+ : protoName(name), protoAlias(alias) {}
+
+private:
+ const char *protoName;
+ const char *protoAlias;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState.cpp b/libraries/NoiseProtocol/src/NoiseSymmetricState.cpp
new file mode 100644
index 00000000..18a02771
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseSymmetricState.h"
+
+/**
+ * \class NoiseSymmetricState NoiseSymmetricState.h
+ * \brief Abstract base class for the Noise protocol's symmetric state.
+ *
+ * This class is abstract. The caller should instantiate a subclass like
+ * NoiseSymmetricState_ChaChaPoly_BLAKE2s or NoiseSymmetricState_AESGCM_SHA256
+ * to choose the specific algorithms to use in the symmetric state.
+ */
+
+/**
+ * \fn NoiseSymmetricState::NoiseSymmetricState()
+ * \brief Constructs a new symmetric state object.
+ */
+
+/**
+ * \brief Destroys this symmetric state object.
+ */
+NoiseSymmetricState::~NoiseSymmetricState()
+{
+}
+
+/**
+ * \fn void NoiseSymmetricState::initialize(const char *protocolName)
+ * \brief Initializes a Noise protocol using this symmetric state.
+ *
+ * \param protocolName The full name of the Noise protocol.
+ */
+
+/**
+ * \fn bool NoiseSymmetricState::hasKey() const
+ * \brief Determine if this symmetric state has an encryption key set.
+ *
+ * \return Returns true if an encryption key has been set, false if not.
+ */
+
+/**
+ * \brief Returns the length of MAC values for this symmetric state.
+ *
+ * \return The base class returns 16 which is the recommended size for
+ * MAC values in all Noise protocols.
+ *
+ * In theory, subclasses could return a smaller value than 16 if MAC values
+ * were being truncated to save packet space. The Noise specification
+ * recommends against MAC truncation as it reduces security.
+ */
+size_t NoiseSymmetricState::macLen() const
+{
+ return 16;
+}
+
+/**
+ * \fn void NoiseSymmetricState::mixKey(const void *data, size_t size)
+ * \brief Mixes input data into the chaining key.
+ *
+ * \param data Points to the data to be mixed in.
+ * \param size Number of bytes to mix in.
+ *
+ * \sa mixHash(), mixKeyAndHash()
+ */
+
+/**
+ * \fn void NoiseSymmetricState::mixHash(const void *data, size_t size)
+ * \brief Mixes input data into the handshake hash.
+ *
+ * \param data Points to the data to be mixed in.
+ * \param size Number of bytes to mix in.
+ *
+ * \sa mixKey(), mixKeyAndHash()
+ */
+
+/**
+ * \fn void NoiseSymmetricState::mixKeyAndHash(const void *data, size_t size)
+ * \brief Mixes input data into the chaining key and handshake hash.
+ *
+ * \param data Points to the data to be mixed in.
+ * \param size Number of bytes to mix in.
+ *
+ * \sa mixKey(), mixHash()
+ */
+
+/**
+ * \fn void NoiseSymmetricState::getHandshakeHash(void *data, size_t size)
+ * \brief Gets the handshake hash from the symmetric state.
+ *
+ * \param data Data buffer to fill with the handshake hash.
+ * \param size Size of the \a data buffer in bytes.
+ *
+ * If \a size is less than the size of the symmetric state's hash,
+ * then the value will be truncated to the first \a size bytes.
+ * If \a size is greater, then the extra bytes will be filled with zeroes.
+ */
+
+/**
+ * \fn int NoiseSymmetricState::encryptAndHash(uint8_t *output, size_t outputSize, const uint8_t *input, size_t inputSize)
+ * \brief Encrypts data and hashes it into the handshake hash.
+ *
+ * \param output Output buffer to write the ciphertext and MAC to.
+ * \param outputSize Available space in the \a output buffer.
+ * \param input Input buffer containing the plaintext to be encrypted.
+ * \param inputSize Number of bytes of plaintext.
+ *
+ * \return The number of bytes that were written to \a output.
+ * \return -1 if \a outputSize is not large enough to contain the
+ * ciphertext and MAC.
+ *
+ * The plaintext will be copied directly to the output buffer without a MAC
+ * if mixKey() has not been called yet.
+ *
+ * \sa decryptAndHash()
+ */
+
+/**
+ * \fn int NoiseSymmetricState::decryptAndHash(uint8_t *output, size_t outputSize, const uint8_t *input, size_t inputSize)
+ * \brief Decrypts data and hashes it into the handshake hash.
+ *
+ * \param output Output buffer to write the plaintext to.
+ * \param outputSize Available space in the \a output buffer.
+ * \param input Input buffer containing the ciphertext and MAC.
+ * \param inputSize Number of bytes of ciphertext plus the MAC.
+ *
+ * \return The number of bytes that were written to \a output.
+ * \return -1 if \a outputSize is not large enough to contain the plaintext.
+ * \return -1 if the MAC check failed; the plaintext output will be invalid.
+ *
+ * The ciphertext will be copied directly to the output buffer without
+ * removing a MAC if mixKey() has not been called yet.
+ *
+ * \sa encryptAndHash()
+ */
+
+/**
+ * \fn void NoiseSymmetricState::split(NoiseCipherState **c1, NoiseCipherState **c2)
+ * \brief Splits the symmetric state into two cipher objects for the
+ * transport phase of the Noise session.
+ *
+ * \param c1 Returns a new cipher object for encrypting traffic from the
+ * initiator to the responder. May be NULL if the object is not required.
+ * \param c2 Returns a new cipher object for encrypting traffic from the
+ * responder to the initiator. May be NULL if the object is not required.
+ */
+
+/**
+ * \fn void NoiseSymmetricState::clear()
+ * \brief Clears all sensitive data from this symmetric state object.
+ */
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState.h b/libraries/NoiseProtocol/src/NoiseSymmetricState.h
new file mode 100644
index 00000000..a1e72d3e
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_SYMMETRIC_STATE_h
+#define NOISE_SYMMETRIC_STATE_h
+
+#include
+#include
+
+class NoiseCipherState;
+
+class NoiseSymmetricState
+{
+public:
+ NoiseSymmetricState() {}
+ virtual ~NoiseSymmetricState();
+
+ virtual void initialize(const char *protocolName) = 0;
+
+ virtual bool hasKey() const = 0;
+ virtual size_t macLen() const;
+
+ virtual void mixKey(const void *data, size_t size) = 0;
+ virtual void mixHash(const void *data, size_t size) = 0;
+ virtual void mixKeyAndHash(const void *data, size_t size) = 0;
+
+ virtual void getHandshakeHash(void *data, size_t size) = 0;
+
+ virtual int encryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize) = 0;
+ virtual int decryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize) = 0;
+
+ virtual void split(NoiseCipherState **c1, NoiseCipherState **c2) = 0;
+
+ virtual void clear() = 0;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState_AESGCM_SHA256.cpp b/libraries/NoiseProtocol/src/NoiseSymmetricState_AESGCM_SHA256.cpp
new file mode 100644
index 00000000..9774b07d
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState_AESGCM_SHA256.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseSymmetricState_AESGCM_SHA256.h"
+#include "NoiseCipherState_AESGCM.h"
+#include "SHA256.h"
+#include "Crypto.h"
+#include
+
+/**
+ * \class NoiseSymmetricState_AESGCM_SHA256 NoiseSymmetricState_AESGCM_SHA256.h
+ * \brief Noise symmetric state implementation using AES256, GCM, and SHA256.
+ */
+
+/**
+ * \brief Constructs a new symmetric state using AES256, GCM, and SHA256.
+ */
+NoiseSymmetricState_AESGCM_SHA256::NoiseSymmetricState_AESGCM_SHA256()
+{
+ st.n = 0;
+ st.hasKey = false;
+}
+
+/**
+ * \brief Destroys this symmetric state object.
+ */
+NoiseSymmetricState_AESGCM_SHA256::~NoiseSymmetricState_AESGCM_SHA256()
+{
+ clean(st);
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::initialize
+ (const char *protocolName)
+{
+ size_t len = strlen(protocolName);
+ if (len <= 32) {
+ memcpy(st.h, protocolName, len);
+ memset(st.h + len, 0, 32 - len);
+ } else {
+ SHA256 hash;
+ hash.update(protocolName, len);
+ hash.finalize(st.h, 32);
+ }
+ memcpy(st.ck, st.h, 32);
+ st.hasKey = false;
+}
+
+bool NoiseSymmetricState_AESGCM_SHA256::hasKey() const
+{
+ return st.hasKey;
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::mixKey
+ (const void *data, size_t size)
+{
+ uint8_t key[32];
+ hmac(key, st.ck, data, size, 0);
+ hmac(st.ck, key, 0, 0, 1);
+ hmac(key, key, st.ck, 32, 2);
+ st.hasKey = true;
+ st.n = 0;
+ cipher.setKey(key, sizeof(key));
+ clean(key);
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::mixHash
+ (const void *data, size_t size)
+{
+ SHA256 hash;
+ hash.update(st.h, sizeof(st.h));
+ hash.update(data, size);
+ hash.finalize(st.h, sizeof(st.h));
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::mixKeyAndHash
+ (const void *data, size_t size)
+{
+ uint8_t key[32];
+ uint8_t temph[32];
+ hmac(key, st.ck, data, size, 0);
+ hmac(st.ck, key, 0, 0, 1);
+ hmac(temph, key, st.ck, 32, 2);
+ hmac(key, key, temph, 32, 3);
+ st.hasKey = true;
+ st.n = 0;
+ cipher.setKey(key, sizeof(key));
+ mixHash(temph, sizeof(temph));
+ clean(key);
+ clean(temph);
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::getHandshakeHash
+ (void *data, size_t size)
+{
+ if (size <= 32) {
+ memcpy(data, st.h, size);
+ } else {
+ memcpy(data, st.h, 32);
+ memset(((uint8_t *)data) + 32, 0, size - 32);
+ }
+}
+
+/**
+ * \brief Formats the 12-byte IV for use with AESGCM according
+ * to the requirements of the Noise specification.
+ *
+ * \param iv Returns the formatted IV.
+ * \param n 64-bit nonce value for the packet.
+ */
+void noiseAESGCMFormatIV(uint8_t iv[12], uint64_t n)
+{
+ iv[0] = 0;
+ iv[1] = 0;
+ iv[2] = 0;
+ iv[3] = 0;
+ iv[4] = (uint8_t)(n >> 56);
+ iv[5] = (uint8_t)(n >> 48);
+ iv[6] = (uint8_t)(n >> 40);
+ iv[7] = (uint8_t)(n >> 32);
+ iv[8] = (uint8_t)(n >> 24);
+ iv[9] = (uint8_t)(n >> 16);
+ iv[10] = (uint8_t)(n >> 8);
+ iv[11] = (uint8_t)n;
+}
+
+int NoiseSymmetricState_AESGCM_SHA256::encryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize)
+{
+ if (st.hasKey) {
+ if (outputSize < 16 || (outputSize - 16) < inputSize)
+ return -1;
+ uint8_t iv[24];
+ noiseAESGCMFormatIV(iv, st.n);
+ cipher.setIV(iv, sizeof(iv));
+ cipher.encrypt(output, input, inputSize);
+ cipher.computeTag(output + inputSize, 16);
+ mixHash(output, inputSize + 16);
+ ++st.n;
+ return inputSize + 16;
+ } else {
+ if (outputSize < inputSize)
+ return -1;
+ memcpy(output, input, inputSize);
+ mixHash(output, inputSize);
+ return inputSize;
+ }
+}
+
+int NoiseSymmetricState_AESGCM_SHA256::decryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize)
+{
+ if (st.hasKey) {
+ if (inputSize < 16 || outputSize < (inputSize - 16))
+ return -1;
+ outputSize = inputSize - 16;
+ mixHash(input, inputSize);
+ uint8_t iv[24];
+ noiseAESGCMFormatIV(iv, st.n);
+ cipher.setIV(iv, sizeof(iv));
+ cipher.decrypt(output, input, outputSize);
+ if (cipher.checkTag(input + outputSize, 16)) {
+ ++st.n;
+ return outputSize;
+ }
+ memset(output, 0, outputSize); // Destroy output if tag is incorrect.
+ return -1;
+ } else {
+ if (outputSize < inputSize)
+ return -1;
+ mixHash(input, inputSize);
+ memcpy(output, input, inputSize);
+ return inputSize;
+ }
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::split
+ (NoiseCipherState **c1, NoiseCipherState **c2)
+{
+ uint8_t k1[32];
+ uint8_t k2[32];
+ hmac(k2, st.ck, 0, 0, 0);
+ hmac(k1, k2, 0, 0, 1);
+ hmac(k2, k2, k1, 32, 2);
+ if (c1)
+ *c1 = new NoiseCipherState_AESGCM(k1);
+ if (c2)
+ *c2 = new NoiseCipherState_AESGCM(k2);
+ clean(k1);
+ clean(k2);
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::clear()
+{
+ clean(st);
+ st.n = 0;
+ st.hasKey = false;
+}
+
+void NoiseSymmetricState_AESGCM_SHA256::hmac
+ (uint8_t *output, const uint8_t *key,
+ const void *data, size_t size, uint8_t tag)
+{
+ SHA256 hash;
+ hash.resetHMAC(key, 32);
+ hash.update(data, size);
+ if (tag != 0)
+ hash.update(&tag, 1);
+ hash.finalizeHMAC(key, 32, output, 32);
+}
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState_AESGCM_SHA256.h b/libraries/NoiseProtocol/src/NoiseSymmetricState_AESGCM_SHA256.h
new file mode 100644
index 00000000..de169308
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState_AESGCM_SHA256.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_SYMMETRIC_STATE_AESGCM_SHA256_H
+#define NOISE_SYMMETRIC_STATE_AESGCM_SHA256_H
+
+#include "NoiseSymmetricState.h"
+#include "AES.h"
+#include "GCM.h"
+
+class NoiseSymmetricState_AESGCM_SHA256 : public NoiseSymmetricState
+{
+public:
+ NoiseSymmetricState_AESGCM_SHA256();
+ virtual ~NoiseSymmetricState_AESGCM_SHA256();
+
+ void initialize(const char *protocolName);
+
+ bool hasKey() const;
+
+ void mixKey(const void *data, size_t size);
+ void mixHash(const void *data, size_t size);
+ void mixKeyAndHash(const void *data, size_t size);
+
+ void getHandshakeHash(void *data, size_t size);
+
+ int encryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize);
+ int decryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize);
+
+ void split(NoiseCipherState **c1, NoiseCipherState **c2);
+
+ void clear();
+
+private:
+ GCM cipher;
+ struct {
+ uint8_t ck[32];
+ uint8_t h[32];
+ uint64_t n;
+ bool hasKey;
+ } st;
+
+ static void hmac(uint8_t *output, const uint8_t *key,
+ const void *data, size_t size, uint8_t tag);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_BLAKE2s.cpp b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_BLAKE2s.cpp
new file mode 100644
index 00000000..90059aa1
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_BLAKE2s.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseSymmetricState_ChaChaPoly_BLAKE2s.h"
+#include "NoiseCipherState_ChaChaPoly.h"
+#include "ChaChaPoly.h"
+#include "BLAKE2s.h"
+#include "Crypto.h"
+#include "utility/EndianUtil.h"
+#include
+
+/**
+ * \class NoiseSymmetricState_ChaChaPoly_BLAKE2s NoiseSymmetricState_ChaChaPoly_BLAKE2s.h
+ * \brief Noise symmetric state implementation using ChaChaPoly and BLAKE2s.
+ */
+
+/**
+ * \brief Constructs a new symmetric state using ChaChaPoly and BLAKE2s.
+ */
+NoiseSymmetricState_ChaChaPoly_BLAKE2s::NoiseSymmetricState_ChaChaPoly_BLAKE2s()
+{
+ st.n = 0;
+ st.hasKey = false;
+}
+
+/**
+ * \brief Destroys this symmetric state object.
+ */
+NoiseSymmetricState_ChaChaPoly_BLAKE2s::~NoiseSymmetricState_ChaChaPoly_BLAKE2s()
+{
+ clean(st);
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::initialize
+ (const char *protocolName)
+{
+ size_t len = strlen(protocolName);
+ if (len <= 32) {
+ memcpy(st.h, protocolName, len);
+ memset(st.h + len, 0, 32 - len);
+ } else {
+ BLAKE2s hash;
+ hash.update(protocolName, len);
+ hash.finalize(st.h, 32);
+ }
+ memcpy(st.ck, st.h, 32);
+ st.hasKey = false;
+}
+
+bool NoiseSymmetricState_ChaChaPoly_BLAKE2s::hasKey() const
+{
+ return st.hasKey;
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixKey
+ (const void *data, size_t size)
+{
+ hmac(st.key, st.ck, data, size, 0);
+ hmac(st.ck, st.key, 0, 0, 1);
+ hmac(st.key, st.key, st.ck, 32, 2);
+ st.hasKey = true;
+ st.n = 0;
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixHash
+ (const void *data, size_t size)
+{
+ BLAKE2s hash;
+ hash.update(st.h, sizeof(st.h));
+ hash.update(data, size);
+ hash.finalize(st.h, sizeof(st.h));
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixKeyAndHash
+ (const void *data, size_t size)
+{
+ uint8_t temph[32];
+ hmac(st.key, st.ck, data, size, 0);
+ hmac(st.ck, st.key, 0, 0, 1);
+ hmac(temph, st.key, st.ck, 32, 2);
+ hmac(st.key, st.key, temph, 32, 3);
+ st.hasKey = true;
+ st.n = 0;
+ mixHash(temph, 32);
+ clean(temph);
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::getHandshakeHash
+ (void *data, size_t size)
+{
+ if (size <= 32) {
+ memcpy(data, st.h, size);
+ } else {
+ memcpy(data, st.h, 32);
+ memset(((uint8_t *)data) + 32, 0, size - 32);
+ }
+}
+
+int NoiseSymmetricState_ChaChaPoly_BLAKE2s::encryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize)
+{
+ if (st.hasKey) {
+ if (outputSize < 16 || (outputSize - 16) < inputSize)
+ return -1;
+ ChaChaPoly cipher;
+ uint64_t iv = htole64(st.n);
+ cipher.setKey(st.key, 32);
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.encrypt(output, input, inputSize);
+ cipher.computeTag(output + inputSize, 16);
+ mixHash(output, inputSize + 16);
+ ++st.n;
+ return inputSize + 16;
+ } else {
+ if (outputSize < inputSize)
+ return -1;
+ memcpy(output, input, inputSize);
+ mixHash(output, inputSize);
+ return inputSize;
+ }
+}
+
+int NoiseSymmetricState_ChaChaPoly_BLAKE2s::decryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize)
+{
+ if (st.hasKey) {
+ if (inputSize < 16 || outputSize < (inputSize - 16))
+ return -1;
+ outputSize = inputSize - 16;
+ mixHash(input, inputSize);
+ ChaChaPoly cipher;
+ uint64_t iv = htole64(st.n);
+ cipher.setKey(st.key, 32);
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.decrypt(output, input, outputSize);
+ if (cipher.checkTag(input + outputSize, 16)) {
+ ++st.n;
+ return outputSize;
+ }
+ memset(output, 0, outputSize); // Destroy output if tag is incorrect.
+ return -1;
+ } else {
+ if (outputSize < inputSize)
+ return -1;
+ mixHash(input, inputSize);
+ memcpy(output, input, inputSize);
+ return inputSize;
+ }
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::split
+ (NoiseCipherState **c1, NoiseCipherState **c2)
+{
+ uint8_t k1[32];
+ uint8_t k2[32];
+ hmac(k2, st.ck, 0, 0, 0);
+ hmac(k1, k2, 0, 0, 1);
+ hmac(k2, k2, k1, 32, 2);
+ if (c1)
+ *c1 = new NoiseCipherState_ChaChaPoly(k1);
+ if (c2)
+ *c2 = new NoiseCipherState_ChaChaPoly(k2);
+ clean(k1);
+ clean(k2);
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::clear()
+{
+ clean(st);
+ st.n = 0;
+ st.hasKey = false;
+}
+
+void NoiseSymmetricState_ChaChaPoly_BLAKE2s::hmac
+ (uint8_t *output, const uint8_t *key,
+ const void *data, size_t size, uint8_t tag)
+{
+ BLAKE2s hash;
+ hash.resetHMAC(key, 32);
+ hash.update(data, size);
+ if (tag != 0)
+ hash.update(&tag, 1);
+ hash.finalizeHMAC(key, 32, output, 32);
+}
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_BLAKE2s.h b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_BLAKE2s.h
new file mode 100644
index 00000000..1861d14c
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_BLAKE2s.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_SYMMETRIC_STATE_CHACHAPOLY_BLAKE2S_H
+#define NOISE_SYMMETRIC_STATE_CHACHAPOLY_BLAKE2S_H
+
+#include "NoiseSymmetricState.h"
+
+class NoiseSymmetricState_ChaChaPoly_BLAKE2s : public NoiseSymmetricState
+{
+public:
+ NoiseSymmetricState_ChaChaPoly_BLAKE2s();
+ virtual ~NoiseSymmetricState_ChaChaPoly_BLAKE2s();
+
+ void initialize(const char *protocolName);
+
+ bool hasKey() const;
+
+ void mixKey(const void *data, size_t size);
+ void mixHash(const void *data, size_t size);
+ void mixKeyAndHash(const void *data, size_t size);
+
+ void getHandshakeHash(void *data, size_t size);
+
+ int encryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize);
+ int decryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize);
+
+ void split(NoiseCipherState **c1, NoiseCipherState **c2);
+
+ void clear();
+
+private:
+ struct {
+ uint8_t ck[32];
+ uint8_t h[32];
+ uint8_t key[32];
+ uint64_t n;
+ bool hasKey;
+ } st;
+
+ static void hmac(uint8_t *output, const uint8_t *key,
+ const void *data, size_t size, uint8_t tag);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_SHA256.cpp b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_SHA256.cpp
new file mode 100644
index 00000000..0d5343a6
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_SHA256.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "NoiseSymmetricState_ChaChaPoly_SHA256.h"
+#include "NoiseCipherState_ChaChaPoly.h"
+#include "ChaChaPoly.h"
+#include "SHA256.h"
+#include "Crypto.h"
+#include "utility/EndianUtil.h"
+#include
+
+/**
+ * \class NoiseSymmetricState_ChaChaPoly_SHA256 NoiseSymmetricState_ChaChaPoly_SHA256.h
+ * \brief Noise symmetric state implementation using ChaChaPoly and SHA256.
+ */
+
+/**
+ * \brief Constructs a new symmetric state using ChaChaPoly and SHA256.
+ */
+NoiseSymmetricState_ChaChaPoly_SHA256::NoiseSymmetricState_ChaChaPoly_SHA256()
+{
+ st.n = 0;
+ st.hasKey = false;
+}
+
+/**
+ * \brief Destroys this symmetric state object.
+ */
+NoiseSymmetricState_ChaChaPoly_SHA256::~NoiseSymmetricState_ChaChaPoly_SHA256()
+{
+ clean(st);
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::initialize
+ (const char *protocolName)
+{
+ size_t len = strlen(protocolName);
+ if (len <= 32) {
+ memcpy(st.h, protocolName, len);
+ memset(st.h + len, 0, 32 - len);
+ } else {
+ SHA256 hash;
+ hash.update(protocolName, len);
+ hash.finalize(st.h, 32);
+ }
+ memcpy(st.ck, st.h, 32);
+ st.hasKey = false;
+}
+
+bool NoiseSymmetricState_ChaChaPoly_SHA256::hasKey() const
+{
+ return st.hasKey;
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::mixKey
+ (const void *data, size_t size)
+{
+ hmac(st.key, st.ck, data, size, 0);
+ hmac(st.ck, st.key, 0, 0, 1);
+ hmac(st.key, st.key, st.ck, 32, 2);
+ st.hasKey = true;
+ st.n = 0;
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::mixHash
+ (const void *data, size_t size)
+{
+ SHA256 hash;
+ hash.update(st.h, sizeof(st.h));
+ hash.update(data, size);
+ hash.finalize(st.h, sizeof(st.h));
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::mixKeyAndHash
+ (const void *data, size_t size)
+{
+ uint8_t temph[32];
+ hmac(st.key, st.ck, data, size, 0);
+ hmac(st.ck, st.key, 0, 0, 1);
+ hmac(temph, st.key, st.ck, 32, 2);
+ hmac(st.key, st.key, temph, 32, 3);
+ st.hasKey = true;
+ st.n = 0;
+ mixHash(temph, 32);
+ clean(temph);
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::getHandshakeHash
+ (void *data, size_t size)
+{
+ if (size <= 32) {
+ memcpy(data, st.h, size);
+ } else {
+ memcpy(data, st.h, 32);
+ memset(((uint8_t *)data) + 32, 0, size - 32);
+ }
+}
+
+int NoiseSymmetricState_ChaChaPoly_SHA256::encryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize)
+{
+ if (st.hasKey) {
+ if (outputSize < 16 || (outputSize - 16) < inputSize)
+ return -1;
+ ChaChaPoly cipher;
+ uint64_t iv = htole64(st.n);
+ cipher.setKey(st.key, 32);
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.encrypt(output, input, inputSize);
+ cipher.computeTag(output + inputSize, 16);
+ mixHash(output, inputSize + 16);
+ ++st.n;
+ return inputSize + 16;
+ } else {
+ if (outputSize < inputSize)
+ return -1;
+ memcpy(output, input, inputSize);
+ mixHash(output, inputSize);
+ return inputSize;
+ }
+}
+
+int NoiseSymmetricState_ChaChaPoly_SHA256::decryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize)
+{
+ if (st.hasKey) {
+ if (inputSize < 16 || outputSize < (inputSize - 16))
+ return -1;
+ outputSize = inputSize - 16;
+ mixHash(input, inputSize);
+ ChaChaPoly cipher;
+ uint64_t iv = htole64(st.n);
+ cipher.setKey(st.key, 32);
+ cipher.setIV((const uint8_t *)&iv, sizeof(iv));
+ cipher.decrypt(output, input, outputSize);
+ if (cipher.checkTag(input + outputSize, 16)) {
+ ++st.n;
+ return outputSize;
+ }
+ memset(output, 0, outputSize); // Destroy output if tag is incorrect.
+ return -1;
+ } else {
+ if (outputSize < inputSize)
+ return -1;
+ mixHash(input, inputSize);
+ memcpy(output, input, inputSize);
+ return inputSize;
+ }
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::split
+ (NoiseCipherState **c1, NoiseCipherState **c2)
+{
+ uint8_t k1[32];
+ uint8_t k2[32];
+ hmac(k2, st.ck, 0, 0, 0);
+ hmac(k1, k2, 0, 0, 1);
+ hmac(k2, k2, k1, 32, 2);
+ if (c1)
+ *c1 = new NoiseCipherState_ChaChaPoly(k1);
+ if (c2)
+ *c2 = new NoiseCipherState_ChaChaPoly(k2);
+ clean(k1);
+ clean(k2);
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::clear()
+{
+ clean(st);
+ st.n = 0;
+ st.hasKey = false;
+}
+
+void NoiseSymmetricState_ChaChaPoly_SHA256::hmac
+ (uint8_t *output, const uint8_t *key,
+ const void *data, size_t size, uint8_t tag)
+{
+ SHA256 hash;
+ hash.resetHMAC(key, 32);
+ hash.update(data, size);
+ if (tag != 0)
+ hash.update(&tag, 1);
+ hash.finalizeHMAC(key, 32, output, 32);
+}
diff --git a/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_SHA256.h b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_SHA256.h
new file mode 100644
index 00000000..b66ddb8d
--- /dev/null
+++ b/libraries/NoiseProtocol/src/NoiseSymmetricState_ChaChaPoly_SHA256.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_SYMMETRIC_STATE_CHACHAPOLY_SHA256_H
+#define NOISE_SYMMETRIC_STATE_CHACHAPOLY_SHA256_H
+
+#include "NoiseSymmetricState.h"
+
+class NoiseSymmetricState_ChaChaPoly_SHA256 : public NoiseSymmetricState
+{
+public:
+ NoiseSymmetricState_ChaChaPoly_SHA256();
+ virtual ~NoiseSymmetricState_ChaChaPoly_SHA256();
+
+ void initialize(const char *protocolName);
+
+ bool hasKey() const;
+
+ void mixKey(const void *data, size_t size);
+ void mixHash(const void *data, size_t size);
+ void mixKeyAndHash(const void *data, size_t size);
+
+ void getHandshakeHash(void *data, size_t size);
+
+ int encryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize);
+ int decryptAndHash
+ (uint8_t *output, size_t outputSize,
+ const uint8_t *input, size_t inputSize);
+
+ void split(NoiseCipherState **c1, NoiseCipherState **c2);
+
+ void clear();
+
+private:
+ struct {
+ uint8_t ck[32];
+ uint8_t h[32];
+ uint8_t key[32];
+ uint64_t n;
+ bool hasKey;
+ } st;
+
+ static void hmac(uint8_t *output, const uint8_t *key,
+ const void *data, size_t size, uint8_t tag);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_IK.cpp b/libraries/NoiseProtocol/src/Noise_IK.cpp
new file mode 100644
index 00000000..1b6d036b
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_IK.h"
+
+/**
+ * \class NoiseHandshakeState_IK Noise_IK.h
+ * \brief Handshake implementation of the Noise "IK" pattern.
+ *
+ * The "IK" pattern provides mutual authentication of the two communicating
+ * parties, with the identifying key for the initiating party sent during
+ * the handshake. The identifying key for the responding party is assumed
+ * to already be known to the initiator. If the responding party's key
+ * changes, then the application will need to transition to "XXfallback"
+ * to discover the new key.
+ *
+ * This class provides the core "IK" functionality. Subclasses provide
+ * implementations of "IK" that use specific algorithms, such as
+ * Noise_IK_25519_ChaChaPoly_BLAKE2s.
+ */
+
+/**
+ * \fn NoiseHandshakeState_IK::NoiseHandshakeState_IK()
+ * \brief Constructs a new Noise handshake that uses the IK pattern.
+ */
+
+/**
+ * \brief Destroys this Noise handshake.
+ */
+NoiseHandshakeState_IK::~NoiseHandshakeState_IK()
+{
+}
+
+void NoiseHandshakeState_IK::writeTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ write_e(packet);
+ write_es(packet);
+ write_s(packet);
+ write_ss(packet);
+ } else if (msgnum == 1) {
+ write_e(packet);
+ write_ee(packet);
+ write_se(packet);
+ packet.done = true;
+ }
+}
+
+void NoiseHandshakeState_IK::readTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ read_e(packet);
+ read_es(packet);
+ read_s(packet);
+ read_ss(packet);
+ } else if (msgnum == 1) {
+ read_e(packet);
+ read_ee(packet);
+ read_se(packet);
+ packet.done = true;
+ }
+}
diff --git a/libraries/NoiseProtocol/src/Noise_IK.h b/libraries/NoiseProtocol/src/Noise_IK.h
new file mode 100644
index 00000000..bd30e424
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_IK_h
+#define NOISE_IK_h
+
+#include "NoiseHandshakeState.h"
+
+class NoiseHandshakeState_IK : public NoiseHandshakeState
+{
+public:
+ virtual ~NoiseHandshakeState_IK();
+
+protected:
+ NoiseHandshakeState_IK() {}
+
+ void writeTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+ void readTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_IK_25519_AESGCM_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_IK_25519_AESGCM_SHA256.cpp
new file mode 100644
index 00000000..88868f4c
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK_25519_AESGCM_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_IK_25519_AESGCM_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_IK_25519_AESGCM_SHA256 Noise_IK_25519_AESGCM_SHA256.h
+ * \brief "IK" Noise handshake, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+/**
+ * \class Noise_IK_25519_AESGCM_SHA256 Noise_IK_25519_AESGCM_SHA256.h
+ * \brief "IK" Noise descriptor, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+static char const Noise_IK_25519_AESGCM_SHA256_Name[] =
+ "Noise_IK_25519_AESGCM_SHA256";
+
+NoiseHandshakeState_IK_25519_AESGCM_SHA256::NoiseHandshakeState_IK_25519_AESGCM_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_IK_25519_AESGCM_SHA256_Name);
+}
+
+NoiseHandshakeState_IK_25519_AESGCM_SHA256::~NoiseHandshakeState_IK_25519_AESGCM_SHA256()
+{
+}
+
+Noise_IK_25519_AESGCM_SHA256::Noise_IK_25519_AESGCM_SHA256()
+ : NoiseProtocolDescriptor(Noise_IK_25519_AESGCM_SHA256_Name)
+{
+}
+
+Noise_IK_25519_AESGCM_SHA256::~Noise_IK_25519_AESGCM_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_IK_25519_AESGCM_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_IK_25519_AESGCM_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_IK_25519_AESGCM_SHA256.h b/libraries/NoiseProtocol/src/Noise_IK_25519_AESGCM_SHA256.h
new file mode 100644
index 00000000..91f8b0be
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK_25519_AESGCM_SHA256.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_IK_25519_AESGCM_SHA256_h
+#define NOISE_IK_25519_AESGCM_SHA256_h
+
+#include "Noise_IK.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_AESGCM_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_IK_25519_AESGCM_SHA256 : public NoiseHandshakeState_IK
+{
+public:
+ NoiseHandshakeState_IK_25519_AESGCM_SHA256();
+ virtual ~NoiseHandshakeState_IK_25519_AESGCM_SHA256();
+
+private:
+ NoiseSymmetricState_AESGCM_SHA256 sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_IK_25519_AESGCM_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_IK_25519_AESGCM_SHA256();
+ virtual ~Noise_IK_25519_AESGCM_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_BLAKE2s.cpp b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_BLAKE2s.cpp
new file mode 100644
index 00000000..a98bb8b2
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_BLAKE2s.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_IK_25519_ChaChaPoly_BLAKE2s.h"
+
+/**
+ * \class NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s Noise_IK_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "IK" Noise handshake, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+/**
+ * \class Noise_IK_25519_ChaChaPoly_BLAKE2s Noise_IK_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "IK" Noise descriptor, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+static char const Noise_IK_25519_ChaChaPoly_BLAKE2s_Name[] =
+ "Noise_IK_25519_ChaChaPoly_BLAKE2s";
+
+NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s::NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_IK_25519_ChaChaPoly_BLAKE2s_Name);
+}
+
+NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s::~NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+Noise_IK_25519_ChaChaPoly_BLAKE2s::Noise_IK_25519_ChaChaPoly_BLAKE2s()
+ : NoiseProtocolDescriptor(Noise_IK_25519_ChaChaPoly_BLAKE2s_Name)
+{
+}
+
+Noise_IK_25519_ChaChaPoly_BLAKE2s::~Noise_IK_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+NoiseHandshakeState *Noise_IK_25519_ChaChaPoly_BLAKE2s::createHandshake() const
+{
+ return new NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_BLAKE2s.h b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_BLAKE2s.h
new file mode 100644
index 00000000..132d02ee
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_BLAKE2s.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_IK_25519_CHACHAPOLY_BLAKE2S_h
+#define NOISE_IK_25519_CHACHAPOLY_BLAKE2S_h
+
+#include "Noise_IK.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_BLAKE2s.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s
+ : public NoiseHandshakeState_IK
+{
+public:
+ NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s();
+ virtual ~NoiseHandshakeState_IK_25519_ChaChaPoly_BLAKE2s();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_BLAKE2s sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_IK_25519_ChaChaPoly_BLAKE2s : public NoiseProtocolDescriptor
+{
+public:
+ Noise_IK_25519_ChaChaPoly_BLAKE2s();
+ virtual ~Noise_IK_25519_ChaChaPoly_BLAKE2s();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_SHA256.cpp
new file mode 100644
index 00000000..e60eed53
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_IK_25519_ChaChaPoly_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256 Noise_IK_25519_ChaChaPoly_SHA256.h
+ * \brief "IK" Noise handshake, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+/**
+ * \class Noise_IK_25519_ChaChaPoly_SHA256 Noise_IK_25519_ChaChaPoly_SHA256.h
+ * \brief "IK" Noise descriptor, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+static char const Noise_IK_25519_ChaChaPoly_SHA256_Name[] =
+ "Noise_IK_25519_ChaChaPoly_SHA256";
+
+NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256::NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_IK_25519_ChaChaPoly_SHA256_Name);
+}
+
+NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256::~NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256()
+{
+}
+
+Noise_IK_25519_ChaChaPoly_SHA256::Noise_IK_25519_ChaChaPoly_SHA256()
+ : NoiseProtocolDescriptor(Noise_IK_25519_ChaChaPoly_SHA256_Name)
+{
+}
+
+Noise_IK_25519_ChaChaPoly_SHA256::~Noise_IK_25519_ChaChaPoly_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_IK_25519_ChaChaPoly_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_SHA256.h b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_SHA256.h
new file mode 100644
index 00000000..3e95e03e
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_IK_25519_ChaChaPoly_SHA256.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_IK_25519_CHACHAPOLY_SHA256_h
+#define NOISE_IK_25519_CHACHAPOLY_SHA256_h
+
+#include "Noise_IK.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256
+ : public NoiseHandshakeState_IK
+{
+public:
+ NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256();
+ virtual ~NoiseHandshakeState_IK_25519_ChaChaPoly_SHA256();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_SHA256 sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_IK_25519_ChaChaPoly_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_IK_25519_ChaChaPoly_SHA256();
+ virtual ~Noise_IK_25519_ChaChaPoly_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0.cpp b/libraries/NoiseProtocol/src/Noise_NNpsk0.cpp
new file mode 100644
index 00000000..b3c2e586
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_NNpsk0.h"
+
+/**
+ * \class NoiseHandshakeState_NNpsk0 Noise_NNpsk0.h
+ * \brief Handshake implementation of the Noise "NNpsk0" pattern.
+ *
+ * The "NNpsk0" pattern is intended for use in place of "XX" when
+ * the parties have a pre-shared symmetric key (or "PSK").
+ *
+ * This class provides the core "NNpsk0" functionality. Subclasses provide
+ * implementations of "NNpsk0" that use specific algorithms, such as
+ * Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.
+ */
+
+/**
+ * \fn NoiseHandshakeState_NNpsk0::NoiseHandshakeState_NNpsk0()
+ * \brief Constructs a new Noise handshake that uses the NNpsk0 pattern.
+ */
+
+/**
+ * \brief Destroys this Noise handshake.
+ */
+NoiseHandshakeState_NNpsk0::~NoiseHandshakeState_NNpsk0()
+{
+}
+
+void NoiseHandshakeState_NNpsk0::writeTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ write_psk(packet);
+ write_e(packet);
+ } else if (msgnum == 1) {
+ write_e(packet);
+ write_ee(packet);
+ packet.done = true;
+ }
+}
+
+void NoiseHandshakeState_NNpsk0::readTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ read_psk(packet);
+ read_e(packet);
+ } else if (msgnum == 1) {
+ read_e(packet);
+ read_ee(packet);
+ packet.done = true;
+ }
+}
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0.h b/libraries/NoiseProtocol/src/Noise_NNpsk0.h
new file mode 100644
index 00000000..12511827
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_NN_PSK0_h
+#define NOISE_NN_PSK0_h
+
+#include "NoiseHandshakeState.h"
+
+class NoiseHandshakeState_NNpsk0 : public NoiseHandshakeStatePSK
+{
+public:
+ virtual ~NoiseHandshakeState_NNpsk0();
+
+protected:
+ NoiseHandshakeState_NNpsk0() {}
+
+ void writeTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+ void readTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_AESGCM_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_AESGCM_SHA256.cpp
new file mode 100644
index 00000000..719f0323
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_AESGCM_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_NNpsk0_25519_AESGCM_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256 Noise_NNpsk0_25519_AESGCM_SHA256.h
+ * \brief "NNpsk0" Noise handshake, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+/**
+ * \class Noise_NNpsk0_25519_AESGCM_SHA256 Noise_NNpsk0_25519_AESGCM_SHA256.h
+ * \brief "NNpsk0" Noise descriptor, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+static char const Noise_NNpsk0_25519_AESGCM_SHA256_Name[] =
+ "Noise_NNpsk0_25519_AESGCM_SHA256";
+
+NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256::NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_NNpsk0_25519_AESGCM_SHA256_Name);
+}
+
+NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256::~NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256()
+{
+}
+
+Noise_NNpsk0_25519_AESGCM_SHA256::Noise_NNpsk0_25519_AESGCM_SHA256()
+ : NoiseProtocolDescriptor(Noise_NNpsk0_25519_AESGCM_SHA256_Name)
+{
+}
+
+Noise_NNpsk0_25519_AESGCM_SHA256::~Noise_NNpsk0_25519_AESGCM_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_NNpsk0_25519_AESGCM_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_AESGCM_SHA256.h b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_AESGCM_SHA256.h
new file mode 100644
index 00000000..48f0c2c8
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_AESGCM_SHA256.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_NN_PSK0_25519_AESGCM_SHA256_h
+#define NOISE_NN_PSK0_25519_AESGCM_SHA256_h
+
+#include "Noise_NNpsk0.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_AESGCM_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256
+ : public NoiseHandshakeState_NNpsk0
+{
+public:
+ NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256();
+ virtual ~NoiseHandshakeState_NNpsk0_25519_AESGCM_SHA256();
+
+private:
+ NoiseSymmetricState_AESGCM_SHA256 sym;
+ NoiseDHState_Curve25519_EphemOnly dh;
+};
+
+class Noise_NNpsk0_25519_AESGCM_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_NNpsk0_25519_AESGCM_SHA256();
+ virtual ~Noise_NNpsk0_25519_AESGCM_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.cpp b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.cpp
new file mode 100644
index 00000000..7ceffca7
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.h"
+
+/**
+ * \class NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "NNpsk0" Noise handshake, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+/**
+ * \class Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "NNpsk0" Noise descriptor, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+static char const Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s_Name[] =
+ "Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s";
+
+NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s::NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s_Name);
+}
+
+NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s::~NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s::Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s()
+ : NoiseProtocolDescriptor(Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s_Name)
+{
+}
+
+Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s::~Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+NoiseHandshakeState *Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s::createHandshake() const
+{
+ return new NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.h b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.h
new file mode 100644
index 00000000..c89bf7cf
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_NN_PSK0_25519_CHACHAPOLY_BLAKE2S_h
+#define NOISE_NN_PSK0_25519_CHACHAPOLY_BLAKE2S_h
+
+#include "Noise_NNpsk0.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_BLAKE2s.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s
+ : public NoiseHandshakeState_NNpsk0
+{
+public:
+ NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s();
+ virtual ~NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_BLAKE2s();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_BLAKE2s sym;
+ NoiseDHState_Curve25519_EphemOnly dh;
+};
+
+class Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s : public NoiseProtocolDescriptor
+{
+public:
+ Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s();
+ virtual ~Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_SHA256.cpp
new file mode 100644
index 00000000..e51cb4e6
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_NNpsk0_25519_ChaChaPoly_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256 Noise_NNpsk0_25519_ChaChaPoly_SHA256.h
+ * \brief "NNpsk0" Noise handshake, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+/**
+ * \class Noise_NNpsk0_25519_ChaChaPoly_SHA256 Noise_NNpsk0_25519_ChaChaPoly_SHA256.h
+ * \brief "NNpsk0" Noise descriptor, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+static char const Noise_NNpsk0_25519_ChaChaPoly_SHA256_Name[] =
+ "Noise_NNpsk0_25519_ChaChaPoly_SHA256";
+
+NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256::NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_NNpsk0_25519_ChaChaPoly_SHA256_Name);
+}
+
+NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256::~NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256()
+{
+}
+
+Noise_NNpsk0_25519_ChaChaPoly_SHA256::Noise_NNpsk0_25519_ChaChaPoly_SHA256()
+ : NoiseProtocolDescriptor(Noise_NNpsk0_25519_ChaChaPoly_SHA256_Name)
+{
+}
+
+Noise_NNpsk0_25519_ChaChaPoly_SHA256::~Noise_NNpsk0_25519_ChaChaPoly_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_NNpsk0_25519_ChaChaPoly_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_SHA256.h b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_SHA256.h
new file mode 100644
index 00000000..9713853e
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_NNpsk0_25519_ChaChaPoly_SHA256.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_NN_PSK0_25519_CHACHAPOLY_SHA256_h
+#define NOISE_NN_PSK0_25519_CHACHAPOLY_SHA256_h
+
+#include "Noise_NNpsk0.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256
+ : public NoiseHandshakeState_NNpsk0
+{
+public:
+ NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256();
+ virtual ~NoiseHandshakeState_NNpsk0_25519_ChaChaPoly_SHA256();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_SHA256 sym;
+ NoiseDHState_Curve25519_EphemOnly dh;
+};
+
+class Noise_NNpsk0_25519_ChaChaPoly_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_NNpsk0_25519_ChaChaPoly_SHA256();
+ virtual ~Noise_NNpsk0_25519_ChaChaPoly_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_Pipes_25519_AESGCM_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_Pipes_25519_AESGCM_SHA256.cpp
new file mode 100644
index 00000000..b4041344
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_Pipes_25519_AESGCM_SHA256.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_Pipes_25519_AESGCM_SHA256.h"
+
+/**
+ * \class Noise_Pipes_25519_AESGCM_SHA256 Noise_Pipes_25519_AESGCM_SHA256.h
+ * \brief Noise Pipes descriptor, using Curve25519, AES256, GCM, and SHA256.
+ *
+ * Noise Pipes combines the effect of XX, IK, and XXfallback to produce a
+ * protocol that requires only two handshake messages if the responder's
+ * static public key is known, or three handshake messages if the key
+ * is unknown or incorrect.
+ */
+
+Noise_Pipes_25519_AESGCM_SHA256::Noise_Pipes_25519_AESGCM_SHA256()
+{
+}
+
+Noise_Pipes_25519_AESGCM_SHA256::~Noise_Pipes_25519_AESGCM_SHA256()
+{
+}
+
+const NoiseProtocolDescriptor *Noise_Pipes_25519_AESGCM_SHA256::abbreviatedDescriptor() const
+{
+ return &ik;
+}
+
+const NoiseProtocolDescriptor *Noise_Pipes_25519_AESGCM_SHA256::fallbackDescriptor() const
+{
+ return &fallback;
+}
diff --git a/libraries/NoiseProtocol/src/Noise_Pipes_25519_AESGCM_SHA256.h b/libraries/NoiseProtocol/src/Noise_Pipes_25519_AESGCM_SHA256.h
new file mode 100644
index 00000000..1be38abd
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_Pipes_25519_AESGCM_SHA256.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_PIPES_25519_AESGCM_SHA256_h
+#define NOISE_PIPES_25519_AESGCM_SHA256_h
+
+#include "Noise_XX_25519_AESGCM_SHA256.h"
+#include "Noise_IK_25519_AESGCM_SHA256.h"
+#include "Noise_XXfallback_25519_AESGCM_SHA256.h"
+
+class Noise_Pipes_25519_AESGCM_SHA256 :
+ public Noise_XX_25519_AESGCM_SHA256
+{
+public:
+ Noise_Pipes_25519_AESGCM_SHA256();
+ virtual ~Noise_Pipes_25519_AESGCM_SHA256();
+
+ const NoiseProtocolDescriptor *abbreviatedDescriptor() const;
+ const NoiseProtocolDescriptor *fallbackDescriptor() const;
+
+private:
+ Noise_IK_25519_AESGCM_SHA256 ik;
+ Noise_XXfallback_25519_AESGCM_SHA256 fallback;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_BLAKE2s.cpp b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_BLAKE2s.cpp
new file mode 100644
index 00000000..88aea122
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_BLAKE2s.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_Pipes_25519_ChaChaPoly_BLAKE2s.h"
+
+/**
+ * \class Noise_Pipes_25519_ChaChaPoly_BLAKE2s Noise_Pipes_25519_ChaChaPoly_BLAKE2s.h
+ * \brief Noise Pipes descriptor, using Curve25519, ChaChaPoly, and BLAKE2s.
+ *
+ * Noise Pipes combines the effect of XX, IK, and XXfallback to produce a
+ * protocol that requires only two handshake messages if the responder's
+ * static public key is known, or three handshake messages if the key
+ * is unknown or incorrect.
+ */
+
+Noise_Pipes_25519_ChaChaPoly_BLAKE2s::Noise_Pipes_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+Noise_Pipes_25519_ChaChaPoly_BLAKE2s::~Noise_Pipes_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+const NoiseProtocolDescriptor *Noise_Pipes_25519_ChaChaPoly_BLAKE2s::abbreviatedDescriptor() const
+{
+ return &ik;
+}
+
+const NoiseProtocolDescriptor *Noise_Pipes_25519_ChaChaPoly_BLAKE2s::fallbackDescriptor() const
+{
+ return &fallback;
+}
diff --git a/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_BLAKE2s.h b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_BLAKE2s.h
new file mode 100644
index 00000000..5c0d8bef
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_BLAKE2s.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_PIPES_25519_CHACHAPOLY_BLAKE2S_h
+#define NOISE_PIPES_25519_CHACHAPOLY_BLAKE2S_h
+
+#include "Noise_XX_25519_ChaChaPoly_BLAKE2s.h"
+#include "Noise_IK_25519_ChaChaPoly_BLAKE2s.h"
+#include "Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h"
+
+class Noise_Pipes_25519_ChaChaPoly_BLAKE2s :
+ public Noise_XX_25519_ChaChaPoly_BLAKE2s
+{
+public:
+ Noise_Pipes_25519_ChaChaPoly_BLAKE2s();
+ virtual ~Noise_Pipes_25519_ChaChaPoly_BLAKE2s();
+
+ const NoiseProtocolDescriptor *abbreviatedDescriptor() const;
+ const NoiseProtocolDescriptor *fallbackDescriptor() const;
+
+private:
+ Noise_IK_25519_ChaChaPoly_BLAKE2s ik;
+ Noise_XXfallback_25519_ChaChaPoly_BLAKE2s fallback;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_SHA256.cpp
new file mode 100644
index 00000000..5a795acd
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_SHA256.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_Pipes_25519_ChaChaPoly_SHA256.h"
+
+/**
+ * \class Noise_Pipes_25519_ChaChaPoly_SHA256 Noise_Pipes_25519_ChaChaPoly_SHA256.h
+ * \brief Noise Pipes descriptor, using Curve25519, ChaChaPoly, and SHA256.
+ *
+ * Noise Pipes combines the effect of XX, IK, and XXfallback to produce a
+ * protocol that requires only two handshake messages if the responder's
+ * static public key is known, or three handshake messages if the key
+ * is unknown or incorrect.
+ */
+
+Noise_Pipes_25519_ChaChaPoly_SHA256::Noise_Pipes_25519_ChaChaPoly_SHA256()
+{
+}
+
+Noise_Pipes_25519_ChaChaPoly_SHA256::~Noise_Pipes_25519_ChaChaPoly_SHA256()
+{
+}
+
+const NoiseProtocolDescriptor *Noise_Pipes_25519_ChaChaPoly_SHA256::abbreviatedDescriptor() const
+{
+ return &ik;
+}
+
+const NoiseProtocolDescriptor *Noise_Pipes_25519_ChaChaPoly_SHA256::fallbackDescriptor() const
+{
+ return &fallback;
+}
diff --git a/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_SHA256.h b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_SHA256.h
new file mode 100644
index 00000000..69b62e1c
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_Pipes_25519_ChaChaPoly_SHA256.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_PIPES_25519_CHACHAPOLY_SHA256_h
+#define NOISE_PIPES_25519_CHACHAPOLY_SHA256_h
+
+#include "Noise_XX_25519_ChaChaPoly_SHA256.h"
+#include "Noise_IK_25519_ChaChaPoly_SHA256.h"
+#include "Noise_XXfallback_25519_ChaChaPoly_SHA256.h"
+
+class Noise_Pipes_25519_ChaChaPoly_SHA256 :
+ public Noise_XX_25519_ChaChaPoly_SHA256
+{
+public:
+ Noise_Pipes_25519_ChaChaPoly_SHA256();
+ virtual ~Noise_Pipes_25519_ChaChaPoly_SHA256();
+
+ const NoiseProtocolDescriptor *abbreviatedDescriptor() const;
+ const NoiseProtocolDescriptor *fallbackDescriptor() const;
+
+private:
+ Noise_IK_25519_ChaChaPoly_SHA256 ik;
+ Noise_XXfallback_25519_ChaChaPoly_SHA256 fallback;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XX.cpp b/libraries/NoiseProtocol/src/Noise_XX.cpp
new file mode 100644
index 00000000..86809680
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XX.h"
+
+/**
+ * \class NoiseHandshakeState_XX Noise_XX.h
+ * \brief Handshake implementation of the Noise "XX" pattern.
+ *
+ * The "XX" pattern provides mutual authentication of the two communicating
+ * parties, with the identifying keys for the parties exchanged during
+ * the handshake.
+ *
+ * This class provides the core "XX" functionality. Subclasses provide
+ * implementations of "XX" that use specific algorithms, such as
+ * Noise_XX_25519_ChaChaPoly_BLAKE2s.
+ */
+
+/**
+ * \fn NoiseHandshakeState_XX::NoiseHandshakeState_XX()
+ * \brief Constructs a new Noise handshake that uses the XX pattern.
+ */
+
+/**
+ * \brief Destroys this Noise handshake.
+ */
+NoiseHandshakeState_XX::~NoiseHandshakeState_XX()
+{
+}
+
+void NoiseHandshakeState_XX::removeKeys()
+{
+ // Remote static key is expected to be discovered during the XX handshake.
+ // Local static key is preserved because we will eventually need to
+ // send it to the remote party during the XX handshake.
+ removeParameter(Noise::RemoteStaticPublicKey);
+
+ // Base class implementation removes the ephemeral keys.
+ NoiseHandshakeState::removeKeys();
+}
+
+void NoiseHandshakeState_XX::writeTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ write_e(packet);
+ } else if (msgnum == 1) {
+ write_e(packet);
+ write_ee(packet);
+ write_s(packet);
+ write_es(packet);
+ } else if (msgnum == 2) {
+ write_s(packet);
+ write_se(packet);
+ packet.done = true;
+ }
+}
+
+void NoiseHandshakeState_XX::readTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ read_e(packet);
+ } else if (msgnum == 1) {
+ read_e(packet);
+ read_ee(packet);
+ read_s(packet);
+ read_es(packet);
+ } else if (msgnum == 2) {
+ read_s(packet);
+ read_se(packet);
+ packet.done = true;
+ }
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XX.h b/libraries/NoiseProtocol/src/Noise_XX.h
new file mode 100644
index 00000000..74112ea9
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_h
+#define NOISE_XX_h
+
+#include "NoiseHandshakeState.h"
+
+class NoiseHandshakeState_XX : public NoiseHandshakeState
+{
+public:
+ virtual ~NoiseHandshakeState_XX();
+
+protected:
+ NoiseHandshakeState_XX() {}
+
+ void removeKeys();
+ void writeTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+ void readTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XX_25519_AESGCM_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_XX_25519_AESGCM_SHA256.cpp
new file mode 100644
index 00000000..ab34d1a7
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX_25519_AESGCM_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XX_25519_AESGCM_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_XX_25519_AESGCM_SHA256 Noise_XX_25519_AESGCM_SHA256.h
+ * \brief "XX" Noise handshake, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+/**
+ * \class Noise_XX_25519_AESGCM_SHA256 Noise_XX_25519_AESGCM_SHA256.h
+ * \brief "XX" Noise descriptor, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+static char const Noise_XX_25519_AESGCM_SHA256_Name[] =
+ "Noise_XX_25519_AESGCM_SHA256";
+
+NoiseHandshakeState_XX_25519_AESGCM_SHA256::NoiseHandshakeState_XX_25519_AESGCM_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_XX_25519_AESGCM_SHA256_Name);
+}
+
+NoiseHandshakeState_XX_25519_AESGCM_SHA256::~NoiseHandshakeState_XX_25519_AESGCM_SHA256()
+{
+}
+
+Noise_XX_25519_AESGCM_SHA256::Noise_XX_25519_AESGCM_SHA256()
+ : NoiseProtocolDescriptor(Noise_XX_25519_AESGCM_SHA256_Name, "1")
+{
+}
+
+Noise_XX_25519_AESGCM_SHA256::~Noise_XX_25519_AESGCM_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_XX_25519_AESGCM_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_XX_25519_AESGCM_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XX_25519_AESGCM_SHA256.h b/libraries/NoiseProtocol/src/Noise_XX_25519_AESGCM_SHA256.h
new file mode 100644
index 00000000..67042945
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX_25519_AESGCM_SHA256.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_25519_AESGCM_SHA256_h
+#define NOISE_XX_25519_AESGCM_SHA256_h
+
+#include "Noise_XX.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_AESGCM_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_XX_25519_AESGCM_SHA256 : public NoiseHandshakeState_XX
+{
+public:
+ NoiseHandshakeState_XX_25519_AESGCM_SHA256();
+ virtual ~NoiseHandshakeState_XX_25519_AESGCM_SHA256();
+
+private:
+ NoiseSymmetricState_AESGCM_SHA256 sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_XX_25519_AESGCM_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_XX_25519_AESGCM_SHA256();
+ virtual ~Noise_XX_25519_AESGCM_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_BLAKE2s.cpp b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_BLAKE2s.cpp
new file mode 100644
index 00000000..c18a8c2e
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_BLAKE2s.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XX_25519_ChaChaPoly_BLAKE2s.h"
+
+/**
+ * \class NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s Noise_XX_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "XX" Noise handshake, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+/**
+ * \class Noise_XX_25519_ChaChaPoly_BLAKE2s Noise_XX_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "XX" Noise descriptor, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+static char const Noise_XX_25519_ChaChaPoly_BLAKE2s_Name[] =
+ "Noise_XX_25519_ChaChaPoly_BLAKE2s";
+
+NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s::NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_XX_25519_ChaChaPoly_BLAKE2s_Name);
+}
+
+NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s::~NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+Noise_XX_25519_ChaChaPoly_BLAKE2s::Noise_XX_25519_ChaChaPoly_BLAKE2s()
+ : NoiseProtocolDescriptor(Noise_XX_25519_ChaChaPoly_BLAKE2s_Name, "3")
+{
+}
+
+Noise_XX_25519_ChaChaPoly_BLAKE2s::~Noise_XX_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+NoiseHandshakeState *Noise_XX_25519_ChaChaPoly_BLAKE2s::createHandshake() const
+{
+ return new NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_BLAKE2s.h b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_BLAKE2s.h
new file mode 100644
index 00000000..a3a1af11
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_BLAKE2s.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_25519_CHACHAPOLY_BLAKE2S_h
+#define NOISE_XX_25519_CHACHAPOLY_BLAKE2S_h
+
+#include "Noise_XX.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_BLAKE2s.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s
+ : public NoiseHandshakeState_XX
+{
+public:
+ NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s();
+ virtual ~NoiseHandshakeState_XX_25519_ChaChaPoly_BLAKE2s();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_BLAKE2s sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_XX_25519_ChaChaPoly_BLAKE2s : public NoiseProtocolDescriptor
+{
+public:
+ Noise_XX_25519_ChaChaPoly_BLAKE2s();
+ virtual ~Noise_XX_25519_ChaChaPoly_BLAKE2s();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_SHA256.cpp
new file mode 100644
index 00000000..d3e7af32
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XX_25519_ChaChaPoly_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256 Noise_XX_25519_ChaChaPoly_SHA256.h
+ * \brief "XX" Noise handshake, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+/**
+ * \class Noise_XX_25519_ChaChaPoly_SHA256 Noise_XX_25519_ChaChaPoly_SHA256.h
+ * \brief "XX" Noise descriptor, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+static char const Noise_XX_25519_ChaChaPoly_SHA256_Name[] =
+ "Noise_XX_25519_ChaChaPoly_SHA256";
+
+NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256::NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_XX_25519_ChaChaPoly_SHA256_Name);
+}
+
+NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256::~NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256()
+{
+}
+
+Noise_XX_25519_ChaChaPoly_SHA256::Noise_XX_25519_ChaChaPoly_SHA256()
+ : NoiseProtocolDescriptor(Noise_XX_25519_ChaChaPoly_SHA256_Name, "2")
+{
+}
+
+Noise_XX_25519_ChaChaPoly_SHA256::~Noise_XX_25519_ChaChaPoly_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_XX_25519_ChaChaPoly_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_SHA256.h b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_SHA256.h
new file mode 100644
index 00000000..5ab73adf
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XX_25519_ChaChaPoly_SHA256.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_25519_CHACHAPOLY_SHA256_h
+#define NOISE_XX_25519_CHACHAPOLY_SHA256_h
+
+#include "Noise_XX.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256
+ : public NoiseHandshakeState_XX
+{
+public:
+ NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256();
+ virtual ~NoiseHandshakeState_XX_25519_ChaChaPoly_SHA256();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_SHA256 sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_XX_25519_ChaChaPoly_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_XX_25519_ChaChaPoly_SHA256();
+ virtual ~Noise_XX_25519_ChaChaPoly_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback.cpp b/libraries/NoiseProtocol/src/Noise_XXfallback.cpp
new file mode 100644
index 00000000..56f27f40
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XXfallback.h"
+
+/**
+ * \class NoiseHandshakeState_XXfallback Noise_XXfallback.h
+ * \brief Handshake implementation of the Noise "XXfallback" pattern.
+ *
+ * The "XXfallback" pattern provides mutual authentication of the two
+ * communicating parties after a previous "IK" handshake has failed.
+ * The application should use startFallback() instead of start() to
+ * start the new handshake.
+ *
+ * This class provides the core "XXfallback" functionality. Subclasses provide
+ * implementations of "XXfallback" that use specific algorithms, such as
+ * Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.
+ */
+
+/**
+ * \fn NoiseHandshakeState_XXfallback::NoiseHandshakeState_XXfallback()
+ * \brief Constructs a new Noise handshake that uses the XXfallback pattern.
+ */
+
+/**
+ * \brief Destroys this Noise handshake.
+ */
+NoiseHandshakeState_XXfallback::~NoiseHandshakeState_XXfallback()
+{
+}
+
+bool NoiseHandshakeState_XXfallback::startFallback
+ (const NoiseHandshakeState *fallbackFrom, Noise::Party party,
+ const void *prologue, size_t prologueLen)
+{
+ // Cannot fallback if no previous handshake, or fall back from ourselves.
+ if (!fallbackFrom || fallbackFrom == this) {
+ setState(Noise::Failed);
+ return false;
+ }
+ NoiseDHState *thisDH = dhState();
+
+ // Copy keys from the previous handshake into this one.
+ const NoiseDHState *otherDH = otherDHState(fallbackFrom);
+ if (!thisDH || !otherDH || !thisDH->fallback(party, otherDH)) {
+ setState(Noise::Failed);
+ return false;
+ }
+
+ // Start the new handshake.
+ start(party, prologue, prologueLen);
+
+ // Hash the initiator's ephemeral public key from the pre-message.
+ if (party == Noise::Initiator)
+ thisDH->hashPublicKey(symmetricState(), Noise::LocalEphemPublicKey);
+ else
+ thisDH->hashPublicKey(symmetricState(), Noise::RemoteEphemPublicKey);
+
+ // The responder writes first in a XXfallback handshake.
+ setState(party == Noise::Initiator ? Noise::Read : Noise::Write);
+ return true;
+}
+
+void NoiseHandshakeState_XXfallback::removeKeys()
+{
+ // Remove the remote static public key only. We need to keep the
+ // ephemeral keys to perform the fallback correctly.
+ removeParameter(Noise::RemoteStaticPublicKey);
+}
+
+void NoiseHandshakeState_XXfallback::writeTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ write_e(packet);
+ write_ee(packet);
+ write_s(packet);
+ write_es(packet);
+ } else if (msgnum == 1) {
+ write_s(packet);
+ write_se(packet);
+ packet.done = true;
+ }
+}
+
+void NoiseHandshakeState_XXfallback::readTokens
+ (NoiseHandshakeState::Packet &packet, uint8_t msgnum)
+{
+ if (msgnum == 0) {
+ read_e(packet);
+ read_ee(packet);
+ read_s(packet);
+ read_es(packet);
+ } else if (msgnum == 1) {
+ read_s(packet);
+ read_se(packet);
+ packet.done = true;
+ }
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback.h b/libraries/NoiseProtocol/src/Noise_XXfallback.h
new file mode 100644
index 00000000..9174a2d6
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_FALLBACK_h
+#define NOISE_XX_FALLBACK_h
+
+#include "NoiseHandshakeState.h"
+
+class NoiseHandshakeState_XXfallback : public NoiseHandshakeState
+{
+public:
+ virtual ~NoiseHandshakeState_XXfallback();
+
+ bool startFallback
+ (const NoiseHandshakeState *fallbackFrom, Noise::Party party,
+ const void *prologue, size_t prologueLen);
+
+protected:
+ NoiseHandshakeState_XXfallback() {}
+
+ void removeKeys();
+ void writeTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+ void readTokens(NoiseHandshakeState::Packet &packet, uint8_t msgnum);
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback_25519_AESGCM_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_AESGCM_SHA256.cpp
new file mode 100644
index 00000000..9e2ec779
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_AESGCM_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XXfallback_25519_AESGCM_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256 Noise_XXfallback_25519_AESGCM_SHA256.h
+ * \brief "XXfallback" Noise handshake, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+/**
+ * \class Noise_XXfallback_25519_AESGCM_SHA256 Noise_XXfallback_25519_AESGCM_SHA256.h
+ * \brief "XXfallback" Noise descriptor, using Curve25519, AES256, GCM, and SHA256.
+ */
+
+static char const Noise_XXfallback_25519_AESGCM_SHA256_Name[] =
+ "Noise_XXfallback_25519_AESGCM_SHA256";
+
+NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256::NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_XXfallback_25519_AESGCM_SHA256_Name);
+}
+
+NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256::~NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256()
+{
+}
+
+Noise_XXfallback_25519_AESGCM_SHA256::Noise_XXfallback_25519_AESGCM_SHA256()
+ : NoiseProtocolDescriptor(Noise_XXfallback_25519_AESGCM_SHA256_Name)
+{
+}
+
+Noise_XXfallback_25519_AESGCM_SHA256::~Noise_XXfallback_25519_AESGCM_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_XXfallback_25519_AESGCM_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback_25519_AESGCM_SHA256.h b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_AESGCM_SHA256.h
new file mode 100644
index 00000000..01c58338
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_AESGCM_SHA256.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_FALLBACK_25519_AESGCM_SHA256_h
+#define NOISE_XX_FALLBACK_25519_AESGCM_SHA256_h
+
+#include "Noise_XXfallback.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_AESGCM_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256 : public NoiseHandshakeState_XXfallback
+{
+public:
+ NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256();
+ virtual ~NoiseHandshakeState_XXfallback_25519_AESGCM_SHA256();
+
+private:
+ NoiseSymmetricState_AESGCM_SHA256 sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_XXfallback_25519_AESGCM_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_XXfallback_25519_AESGCM_SHA256();
+ virtual ~Noise_XXfallback_25519_AESGCM_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.cpp b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.cpp
new file mode 100644
index 00000000..4569d638
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h"
+
+/**
+ * \class NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "XXfallback" Noise handshake, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+/**
+ * \class Noise_XXfallback_25519_ChaChaPoly_BLAKE2s Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h
+ * \brief "XXfallback" Noise descriptor, using Curve25519, ChaChaPoly, and BLAKE2s.
+ */
+
+static char const Noise_XXfallback_25519_ChaChaPoly_BLAKE2s_Name[] =
+ "Noise_XXfallback_25519_ChaChaPoly_BLAKE2s";
+
+NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s::NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_XXfallback_25519_ChaChaPoly_BLAKE2s_Name);
+}
+
+NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s::~NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+Noise_XXfallback_25519_ChaChaPoly_BLAKE2s::Noise_XXfallback_25519_ChaChaPoly_BLAKE2s()
+ : NoiseProtocolDescriptor(Noise_XXfallback_25519_ChaChaPoly_BLAKE2s_Name)
+{
+}
+
+Noise_XXfallback_25519_ChaChaPoly_BLAKE2s::~Noise_XXfallback_25519_ChaChaPoly_BLAKE2s()
+{
+}
+
+NoiseHandshakeState *Noise_XXfallback_25519_ChaChaPoly_BLAKE2s::createHandshake() const
+{
+ return new NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h
new file mode 100644
index 00000000..dec64eb1
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_BLAKE2s.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_FALLBACK_25519_CHACHAPOLY_BLAKE2S_h
+#define NOISE_XX_FALLBACK_25519_CHACHAPOLY_BLAKE2S_h
+
+#include "Noise_XXfallback.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_BLAKE2s.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s
+ : public NoiseHandshakeState_XXfallback
+{
+public:
+ NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s();
+ virtual ~NoiseHandshakeState_XXfallback_25519_ChaChaPoly_BLAKE2s();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_BLAKE2s sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_XXfallback_25519_ChaChaPoly_BLAKE2s : public NoiseProtocolDescriptor
+{
+public:
+ Noise_XXfallback_25519_ChaChaPoly_BLAKE2s();
+ virtual ~Noise_XXfallback_25519_ChaChaPoly_BLAKE2s();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_SHA256.cpp b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_SHA256.cpp
new file mode 100644
index 00000000..df959a91
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_SHA256.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#include "Noise_XXfallback_25519_ChaChaPoly_SHA256.h"
+
+/**
+ * \class NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256 Noise_XXfallback_25519_ChaChaPoly_SHA256.h
+ * \brief "XXfallback" Noise handshake, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+/**
+ * \class Noise_XXfallback_25519_ChaChaPoly_SHA256 Noise_XXfallback_25519_ChaChaPoly_SHA256.h
+ * \brief "XXfallback" Noise descriptor, using Curve25519, ChaChaPoly, and SHA256.
+ */
+
+static char const Noise_XXfallback_25519_ChaChaPoly_SHA256_Name[] =
+ "Noise_XXfallback_25519_ChaChaPoly_SHA256";
+
+NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256::NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256()
+{
+ setSymmetricState(&sym);
+ setDHState(&dh);
+ setProtocolName(Noise_XXfallback_25519_ChaChaPoly_SHA256_Name);
+}
+
+NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256::~NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256()
+{
+}
+
+Noise_XXfallback_25519_ChaChaPoly_SHA256::Noise_XXfallback_25519_ChaChaPoly_SHA256()
+ : NoiseProtocolDescriptor(Noise_XXfallback_25519_ChaChaPoly_SHA256_Name)
+{
+}
+
+Noise_XXfallback_25519_ChaChaPoly_SHA256::~Noise_XXfallback_25519_ChaChaPoly_SHA256()
+{
+}
+
+NoiseHandshakeState *Noise_XXfallback_25519_ChaChaPoly_SHA256::createHandshake() const
+{
+ return new NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256();
+}
diff --git a/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_SHA256.h b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_SHA256.h
new file mode 100644
index 00000000..3d942bbf
--- /dev/null
+++ b/libraries/NoiseProtocol/src/Noise_XXfallback_25519_ChaChaPoly_SHA256.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOISE_XX_FALLBACK_25519_CHACHAPOLY_SHA256_h
+#define NOISE_XX_FALLBACK_25519_CHACHAPOLY_SHA256_h
+
+#include "Noise_XXfallback.h"
+#include "NoiseProtocolDescriptor.h"
+#include "NoiseSymmetricState_ChaChaPoly_SHA256.h"
+#include "NoiseDHState_Curve25519.h"
+
+class NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256
+ : public NoiseHandshakeState_XXfallback
+{
+public:
+ NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256();
+ virtual ~NoiseHandshakeState_XXfallback_25519_ChaChaPoly_SHA256();
+
+private:
+ NoiseSymmetricState_ChaChaPoly_SHA256 sym;
+ NoiseDHState_Curve25519 dh;
+};
+
+class Noise_XXfallback_25519_ChaChaPoly_SHA256 : public NoiseProtocolDescriptor
+{
+public:
+ Noise_XXfallback_25519_ChaChaPoly_SHA256();
+ virtual ~Noise_XXfallback_25519_ChaChaPoly_SHA256();
+
+ NoiseHandshakeState *createHandshake() const;
+};
+
+#endif