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

Hashing of prologues in sections

This commit is contained in:
Rhys Weatherley 2018-06-21 19:28:52 +10:00
parent 3e3e90b19e
commit 6a71e60d85
11 changed files with 166 additions and 24 deletions

View File

@ -250,8 +250,8 @@ static void test_connection(const TestVector *vec)
/* Should be able to start the handshake now on both sides */
initiator->start
(Noise::Initiator, vec->init_prologue, vec->init_prologue_len);
responder->start
(Noise::Responder, vec->resp_prologue, vec->resp_prologue_len);
responder->start(Noise::Responder);
responder->addPrologue(vec->resp_prologue, vec->resp_prologue_len);
compare(initiator->state(), Noise::Write);
compare(responder->state(), Noise::Read);

View File

@ -85,7 +85,11 @@ NoiseHandshakeState::~NoiseHandshakeState()
* the application should call split() to obtain the cipher objects to use
* to encrypt and decrypt transport messages.
*
* \sa state(), write(), read(), split()
* If the prologue is split into multiple sections, then start() can be
* followed by calls to addPrologue() to add the additional sections
* prior to calling write() or read() for the first time.
*
* \sa state(), write(), read(), split(), addPrologue()
*/
void NoiseHandshakeState::start
(Noise::Party party, const void *prologue, size_t prologueLen)
@ -95,7 +99,26 @@ void NoiseHandshakeState::start
msgnum = 0;
removeKeys();
symmetricState()->initialize(protoName);
symmetricState()->mixHash(prologue, prologueLen);
symmetricState()->mixPrologue(prologue, prologueLen);
}
/**
* \brief Adds additional prologue data to the handshake.
*
* \param prologue Points to the additional prologue data.
* \param prologueLen Length of the prologue additional data in bytes.
*
* \return Returns true if the data was added, or false if the handshake
* is not in the state just after start(). Once the first write() or read()
* occurs, no further prologue data can be added.
*
* \sa start()
*/
bool NoiseHandshakeState::addPrologue(const void *prologue, size_t prologueLen)
{
if (st != Noise::Write && st != Noise::Read)
return false;
return symmetricState()->mixPrologue(prologue, prologueLen);
}
/**

View File

@ -33,8 +33,8 @@ class NoiseHandshakeState
public:
virtual ~NoiseHandshakeState();
virtual void start
(Noise::Party party, const void *prologue = 0, size_t prologueLen = 0);
void start(Noise::Party party, const void *prologue = 0, size_t prologueLen = 0);
bool addPrologue(const void *prologue, size_t prologueLen);
Noise::Party party() const { return pty; }
Noise::HandshakeState state() const { return st; }

View File

@ -72,6 +72,20 @@ size_t NoiseSymmetricState::macLen() const
return 16;
}
/**
* \fn bool NoiseSymmetricState::mixPrologue(const void *data, size_t size)
* \brief Mixes input data into the prologue.
*
* \param data Points to the data to be mixed in.
* \param size Number of bytes to mix in.
*
* \return Returns true if the data was mixed, or false if the prologue
* phase has ended (or never began).
*
* This function must be called just after initialize and before any
* other mixing or encryption operation.
*/
/**
* \fn void NoiseSymmetricState::mixKey(const void *data, size_t size)
* \brief Mixes input data into the chaining key.

View File

@ -39,6 +39,8 @@ public:
virtual bool hasKey() const = 0;
virtual size_t macLen() const;
virtual bool mixPrologue(const void *data, size_t size) = 0;
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;

View File

@ -22,7 +22,6 @@
#include "NoiseSymmetricState_AESGCM_SHA256.h"
#include "NoiseCipherState_AESGCM.h"
#include "SHA256.h"
#include "Crypto.h"
#include <string.h>
@ -38,6 +37,7 @@ NoiseSymmetricState_AESGCM_SHA256::NoiseSymmetricState_AESGCM_SHA256()
{
st.n = 0;
st.hasKey = false;
st.inPrologue = false;
}
/**
@ -56,12 +56,15 @@ void NoiseSymmetricState_AESGCM_SHA256::initialize
memcpy(st.h, protocolName, len);
memset(st.h + len, 0, 32 - len);
} else {
SHA256 hash;
hash.reset();
hash.update(protocolName, len);
hash.finalize(st.h, 32);
}
memcpy(st.ck, st.h, 32);
st.hasKey = false;
hash.reset();
hash.update(st.h, sizeof(st.h));
st.inPrologue = true;
}
bool NoiseSymmetricState_AESGCM_SHA256::hasKey() const
@ -69,10 +72,20 @@ bool NoiseSymmetricState_AESGCM_SHA256::hasKey() const
return st.hasKey;
}
bool NoiseSymmetricState_AESGCM_SHA256::mixPrologue
(const void *data, size_t size)
{
if (!st.inPrologue)
return false;
hash.update(data, size);
return true;
}
void NoiseSymmetricState_AESGCM_SHA256::mixKey
(const void *data, size_t size)
{
uint8_t key[32];
endPrologue();
hmac(key, st.ck, data, size, 0);
hmac(st.ck, key, 0, 0, 1);
hmac(key, key, st.ck, 32, 2);
@ -85,7 +98,8 @@ void NoiseSymmetricState_AESGCM_SHA256::mixKey
void NoiseSymmetricState_AESGCM_SHA256::mixHash
(const void *data, size_t size)
{
SHA256 hash;
endPrologue();
hash.reset();
hash.update(st.h, sizeof(st.h));
hash.update(data, size);
hash.finalize(st.h, sizeof(st.h));
@ -96,6 +110,7 @@ void NoiseSymmetricState_AESGCM_SHA256::mixKeyAndHash
{
uint8_t key[32];
uint8_t temph[32];
endPrologue();
hmac(key, st.ck, data, size, 0);
hmac(st.ck, key, 0, 0, 1);
hmac(temph, key, st.ck, 32, 2);
@ -111,6 +126,7 @@ void NoiseSymmetricState_AESGCM_SHA256::mixKeyAndHash
void NoiseSymmetricState_AESGCM_SHA256::getHandshakeHash
(void *data, size_t size)
{
endPrologue();
if (size <= 32) {
memcpy(data, st.h, size);
} else {
@ -146,6 +162,7 @@ int NoiseSymmetricState_AESGCM_SHA256::encryptAndHash
(uint8_t *output, size_t outputSize,
const uint8_t *input, size_t inputSize)
{
endPrologue();
if (st.hasKey) {
if (outputSize < 16 || (outputSize - 16) < inputSize)
return -1;
@ -171,6 +188,7 @@ int NoiseSymmetricState_AESGCM_SHA256::decryptAndHash
(uint8_t *output, size_t outputSize,
const uint8_t *input, size_t inputSize)
{
endPrologue();
if (st.hasKey) {
if (inputSize < 16 || outputSize < (inputSize - 16))
return -1;
@ -200,6 +218,7 @@ void NoiseSymmetricState_AESGCM_SHA256::split
{
uint8_t k1[32];
uint8_t k2[32];
endPrologue();
hmac(k2, st.ck, 0, 0, 0);
hmac(k1, k2, 0, 0, 1);
hmac(k2, k2, k1, 32, 2);
@ -213,16 +232,24 @@ void NoiseSymmetricState_AESGCM_SHA256::split
void NoiseSymmetricState_AESGCM_SHA256::clear()
{
cipher.clear();
hash.clear();
clean(st);
st.n = 0;
st.hasKey = false;
st.inPrologue = false;
}
void NoiseSymmetricState_AESGCM_SHA256::doEndPrologue()
{
st.inPrologue = false;
hash.finalize(st.h, sizeof(st.h));
}
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)

View File

@ -26,6 +26,7 @@
#include "NoiseSymmetricState.h"
#include "AES.h"
#include "GCM.h"
#include "SHA256.h"
class NoiseSymmetricState_AESGCM_SHA256 : public NoiseSymmetricState
{
@ -37,6 +38,8 @@ public:
bool hasKey() const;
bool mixPrologue(const void *data, size_t size);
void mixKey(const void *data, size_t size);
void mixHash(const void *data, size_t size);
void mixKeyAndHash(const void *data, size_t size);
@ -56,15 +59,20 @@ public:
private:
GCM<AES256> cipher;
SHA256 hash;
struct {
uint8_t ck[32];
uint8_t h[32];
uint64_t n;
bool hasKey;
bool inPrologue;
} st;
static void hmac(uint8_t *output, const uint8_t *key,
const void *data, size_t size, uint8_t tag);
void doEndPrologue();
void endPrologue() { if (st.inPrologue) doEndPrologue(); }
void hmac(uint8_t *output, const uint8_t *key,
const void *data, size_t size, uint8_t tag);
};
#endif

View File

@ -23,7 +23,6 @@
#include "NoiseSymmetricState_ChaChaPoly_BLAKE2s.h"
#include "NoiseCipherState_ChaChaPoly.h"
#include "ChaChaPoly.h"
#include "BLAKE2s.h"
#include "Crypto.h"
#include "utility/EndianUtil.h"
#include <string.h>
@ -40,6 +39,7 @@ NoiseSymmetricState_ChaChaPoly_BLAKE2s::NoiseSymmetricState_ChaChaPoly_BLAKE2s()
{
st.n = 0;
st.hasKey = false;
st.inPrologue = false;
}
/**
@ -58,12 +58,15 @@ void NoiseSymmetricState_ChaChaPoly_BLAKE2s::initialize
memcpy(st.h, protocolName, len);
memset(st.h + len, 0, 32 - len);
} else {
BLAKE2s hash;
hash.reset();
hash.update(protocolName, len);
hash.finalize(st.h, 32);
}
memcpy(st.ck, st.h, 32);
st.hasKey = false;
hash.reset();
hash.update(st.h, sizeof(st.h));
st.inPrologue = true;
}
bool NoiseSymmetricState_ChaChaPoly_BLAKE2s::hasKey() const
@ -71,9 +74,19 @@ bool NoiseSymmetricState_ChaChaPoly_BLAKE2s::hasKey() const
return st.hasKey;
}
bool NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixPrologue
(const void *data, size_t size)
{
if (!st.inPrologue)
return false;
hash.update(data, size);
return true;
}
void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixKey
(const void *data, size_t size)
{
endPrologue();
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);
@ -84,7 +97,8 @@ void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixKey
void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixHash
(const void *data, size_t size)
{
BLAKE2s hash;
endPrologue();
hash.reset();
hash.update(st.h, sizeof(st.h));
hash.update(data, size);
hash.finalize(st.h, sizeof(st.h));
@ -94,6 +108,7 @@ void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixKeyAndHash
(const void *data, size_t size)
{
uint8_t temph[32];
endPrologue();
hmac(st.key, st.ck, data, size, 0);
hmac(st.ck, st.key, 0, 0, 1);
hmac(temph, st.key, st.ck, 32, 2);
@ -107,6 +122,7 @@ void NoiseSymmetricState_ChaChaPoly_BLAKE2s::mixKeyAndHash
void NoiseSymmetricState_ChaChaPoly_BLAKE2s::getHandshakeHash
(void *data, size_t size)
{
endPrologue();
if (size <= 32) {
memcpy(data, st.h, size);
} else {
@ -119,6 +135,7 @@ int NoiseSymmetricState_ChaChaPoly_BLAKE2s::encryptAndHash
(uint8_t *output, size_t outputSize,
const uint8_t *input, size_t inputSize)
{
endPrologue();
if (st.hasKey) {
if (outputSize < 16 || (outputSize - 16) < inputSize)
return -1;
@ -145,6 +162,7 @@ int NoiseSymmetricState_ChaChaPoly_BLAKE2s::decryptAndHash
(uint8_t *output, size_t outputSize,
const uint8_t *input, size_t inputSize)
{
endPrologue();
if (st.hasKey) {
if (inputSize < 16 || outputSize < (inputSize - 16))
return -1;
@ -175,6 +193,7 @@ void NoiseSymmetricState_ChaChaPoly_BLAKE2s::split
{
uint8_t k1[32];
uint8_t k2[32];
endPrologue();
hmac(k2, st.ck, 0, 0, 0);
hmac(k1, k2, 0, 0, 1);
hmac(k2, k2, k1, 32, 2);
@ -188,16 +207,23 @@ void NoiseSymmetricState_ChaChaPoly_BLAKE2s::split
void NoiseSymmetricState_ChaChaPoly_BLAKE2s::clear()
{
hash.clear();
clean(st);
st.n = 0;
st.hasKey = false;
st.inPrologue = false;
}
void NoiseSymmetricState_ChaChaPoly_BLAKE2s::doEndPrologue()
{
st.inPrologue = false;
hash.finalize(st.h, sizeof(st.h));
}
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)

View File

@ -24,6 +24,7 @@
#define NOISE_SYMMETRIC_STATE_CHACHAPOLY_BLAKE2S_H
#include "NoiseSymmetricState.h"
#include "BLAKE2s.h"
class NoiseSymmetricState_ChaChaPoly_BLAKE2s : public NoiseSymmetricState
{
@ -35,6 +36,8 @@ public:
bool hasKey() const;
bool mixPrologue(const void *data, size_t size);
void mixKey(const void *data, size_t size);
void mixHash(const void *data, size_t size);
void mixKeyAndHash(const void *data, size_t size);
@ -53,16 +56,21 @@ public:
void clear();
private:
BLAKE2s hash;
struct {
uint8_t ck[32];
uint8_t h[32];
uint8_t key[32];
uint64_t n;
bool hasKey;
bool inPrologue;
} st;
static void hmac(uint8_t *output, const uint8_t *key,
const void *data, size_t size, uint8_t tag);
void doEndPrologue();
void endPrologue() { if (st.inPrologue) doEndPrologue(); }
void hmac(uint8_t *output, const uint8_t *key,
const void *data, size_t size, uint8_t tag);
};
#endif

View File

@ -23,7 +23,6 @@
#include "NoiseSymmetricState_ChaChaPoly_SHA256.h"
#include "NoiseCipherState_ChaChaPoly.h"
#include "ChaChaPoly.h"
#include "SHA256.h"
#include "Crypto.h"
#include "utility/EndianUtil.h"
#include <string.h>
@ -40,6 +39,7 @@ NoiseSymmetricState_ChaChaPoly_SHA256::NoiseSymmetricState_ChaChaPoly_SHA256()
{
st.n = 0;
st.hasKey = false;
st.inPrologue = false;
}
/**
@ -58,12 +58,15 @@ void NoiseSymmetricState_ChaChaPoly_SHA256::initialize
memcpy(st.h, protocolName, len);
memset(st.h + len, 0, 32 - len);
} else {
SHA256 hash;
hash.reset();
hash.update(protocolName, len);
hash.finalize(st.h, 32);
}
memcpy(st.ck, st.h, 32);
st.hasKey = false;
hash.reset();
hash.update(st.h, sizeof(st.h));
st.inPrologue = true;
}
bool NoiseSymmetricState_ChaChaPoly_SHA256::hasKey() const
@ -71,9 +74,19 @@ bool NoiseSymmetricState_ChaChaPoly_SHA256::hasKey() const
return st.hasKey;
}
bool NoiseSymmetricState_ChaChaPoly_SHA256::mixPrologue
(const void *data, size_t size)
{
if (!st.inPrologue)
return false;
hash.update(data, size);
return true;
}
void NoiseSymmetricState_ChaChaPoly_SHA256::mixKey
(const void *data, size_t size)
{
endPrologue();
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);
@ -84,7 +97,8 @@ void NoiseSymmetricState_ChaChaPoly_SHA256::mixKey
void NoiseSymmetricState_ChaChaPoly_SHA256::mixHash
(const void *data, size_t size)
{
SHA256 hash;
endPrologue();
hash.reset();
hash.update(st.h, sizeof(st.h));
hash.update(data, size);
hash.finalize(st.h, sizeof(st.h));
@ -94,6 +108,7 @@ void NoiseSymmetricState_ChaChaPoly_SHA256::mixKeyAndHash
(const void *data, size_t size)
{
uint8_t temph[32];
endPrologue();
hmac(st.key, st.ck, data, size, 0);
hmac(st.ck, st.key, 0, 0, 1);
hmac(temph, st.key, st.ck, 32, 2);
@ -107,6 +122,7 @@ void NoiseSymmetricState_ChaChaPoly_SHA256::mixKeyAndHash
void NoiseSymmetricState_ChaChaPoly_SHA256::getHandshakeHash
(void *data, size_t size)
{
endPrologue();
if (size <= 32) {
memcpy(data, st.h, size);
} else {
@ -119,6 +135,7 @@ int NoiseSymmetricState_ChaChaPoly_SHA256::encryptAndHash
(uint8_t *output, size_t outputSize,
const uint8_t *input, size_t inputSize)
{
endPrologue();
if (st.hasKey) {
if (outputSize < 16 || (outputSize - 16) < inputSize)
return -1;
@ -145,6 +162,7 @@ int NoiseSymmetricState_ChaChaPoly_SHA256::decryptAndHash
(uint8_t *output, size_t outputSize,
const uint8_t *input, size_t inputSize)
{
endPrologue();
if (st.hasKey) {
if (inputSize < 16 || outputSize < (inputSize - 16))
return -1;
@ -175,6 +193,7 @@ void NoiseSymmetricState_ChaChaPoly_SHA256::split
{
uint8_t k1[32];
uint8_t k2[32];
endPrologue();
hmac(k2, st.ck, 0, 0, 0);
hmac(k1, k2, 0, 0, 1);
hmac(k2, k2, k1, 32, 2);
@ -188,16 +207,23 @@ void NoiseSymmetricState_ChaChaPoly_SHA256::split
void NoiseSymmetricState_ChaChaPoly_SHA256::clear()
{
hash.clear();
clean(st);
st.n = 0;
st.hasKey = false;
st.inPrologue = false;
}
void NoiseSymmetricState_ChaChaPoly_SHA256::doEndPrologue()
{
st.inPrologue = false;
hash.finalize(st.h, sizeof(st.h));
}
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)

View File

@ -24,6 +24,7 @@
#define NOISE_SYMMETRIC_STATE_CHACHAPOLY_SHA256_H
#include "NoiseSymmetricState.h"
#include "SHA256.h"
class NoiseSymmetricState_ChaChaPoly_SHA256 : public NoiseSymmetricState
{
@ -35,6 +36,8 @@ public:
bool hasKey() const;
bool mixPrologue(const void *data, size_t size);
void mixKey(const void *data, size_t size);
void mixHash(const void *data, size_t size);
void mixKeyAndHash(const void *data, size_t size);
@ -53,16 +56,21 @@ public:
void clear();
private:
SHA256 hash;
struct {
uint8_t ck[32];
uint8_t h[32];
uint8_t key[32];
uint64_t n;
bool hasKey;
bool inPrologue;
} st;
static void hmac(uint8_t *output, const uint8_t *key,
const void *data, size_t size, uint8_t tag);
void doEndPrologue();
void endPrologue() { if (st.inPrologue) doEndPrologue(); }
void hmac(uint8_t *output, const uint8_t *key,
const void *data, size_t size, uint8_t tag);
};
#endif