1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Noise protocol implementation

This commit is contained in:
Rhys Weatherley
2018-06-10 16:32:18 +10:00
parent b9fefc6a76
commit 7423609e64
73 changed files with 6800 additions and 1 deletions

View File

@@ -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: <a href="http://tools.ietf.org/html/rfc7748">RFC 7748</a>
*
* \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.
*

View File

@@ -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

View File

@@ -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.
*

View File

@@ -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

View File

@@ -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 <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
}

165
libraries/Crypto/KeyRing.h Normal file
View File

@@ -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 <inttypes.h>
#include <stddef.h>
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