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 */ /* Should be able to start the handshake now on both sides */
initiator->start initiator->start
(Noise::Initiator, vec->init_prologue, vec->init_prologue_len); (Noise::Initiator, vec->init_prologue, vec->init_prologue_len);
responder->start responder->start(Noise::Responder);
(Noise::Responder, vec->resp_prologue, vec->resp_prologue_len); responder->addPrologue(vec->resp_prologue, vec->resp_prologue_len);
compare(initiator->state(), Noise::Write); compare(initiator->state(), Noise::Write);
compare(responder->state(), Noise::Read); 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 * the application should call split() to obtain the cipher objects to use
* to encrypt and decrypt transport messages. * 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 void NoiseHandshakeState::start
(Noise::Party party, const void *prologue, size_t prologueLen) (Noise::Party party, const void *prologue, size_t prologueLen)
@ -95,7 +99,26 @@ void NoiseHandshakeState::start
msgnum = 0; msgnum = 0;
removeKeys(); removeKeys();
symmetricState()->initialize(protoName); 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: public:
virtual ~NoiseHandshakeState(); virtual ~NoiseHandshakeState();
virtual void start void start(Noise::Party party, const void *prologue = 0, size_t prologueLen = 0);
(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::Party party() const { return pty; }
Noise::HandshakeState state() const { return st; } Noise::HandshakeState state() const { return st; }

View File

@ -72,6 +72,20 @@ size_t NoiseSymmetricState::macLen() const
return 16; 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) * \fn void NoiseSymmetricState::mixKey(const void *data, size_t size)
* \brief Mixes input data into the chaining key. * \brief Mixes input data into the chaining key.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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