mirror of
https://github.com/esp8266/Arduino.git
synced 2025-10-16 22:27:59 +03:00
- Replace Crypto files with CryptoInterface which uses BearSSL as a cryptographic backend.
- Move cryptographic functions from JsonTranslator to CryptoInterface. - Make AP activation separate from FloodingMesh::begin(). - Fix English bug. - Improve comments.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,254 +0,0 @@
|
||||
/**
|
||||
* An extremely minimal crypto library for Arduino devices.
|
||||
*
|
||||
* The SHA256 and AES implementations are derived from axTLS
|
||||
* (http://axtls.sourceforge.net/), Copyright (c) 2008, Cameron Rich.
|
||||
*
|
||||
* Ported and refactored by Chris Ellis 2016.
|
||||
* pkcs7 padding routines added by Mike Killewald Nov 26, 2017 (adopted from https://github.com/spaniakos/AES).
|
||||
*
|
||||
License
|
||||
=======
|
||||
Balsa SCGI
|
||||
Copyright (c) 2012, Chris Ellis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_h
|
||||
#define CRYPTO_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined ESP8266
|
||||
#include <osapi.h>
|
||||
#endif
|
||||
|
||||
#define SHA256_SIZE 32
|
||||
#define SHA256HMAC_SIZE 32
|
||||
#define SHA256HMAC_BLOCKSIZE 64
|
||||
#define AES_MAXROUNDS 14
|
||||
#define AES_BLOCKSIZE 16
|
||||
#define AES_IV_SIZE 16
|
||||
#define AES_IV_LENGTH 16
|
||||
#define AES_128_KEY_LENGTH 16
|
||||
#define AES_256_KEY_LENGTH 16
|
||||
|
||||
/**
|
||||
* Compute a SHA256 hash
|
||||
*/
|
||||
class SHA256
|
||||
{
|
||||
public:
|
||||
SHA256();
|
||||
/**
|
||||
* Update the hash with new data
|
||||
*/
|
||||
void doUpdate(const byte *msg, uint32_t len);
|
||||
void doUpdate(const char *msg, unsigned int len) { doUpdate((byte*) msg, len); }
|
||||
void doUpdate(const char *msg) { doUpdate((byte*) msg, strlen(msg)); }
|
||||
/**
|
||||
* Compute the final hash and store it in [digest], digest must be
|
||||
* at least 32 bytes
|
||||
*/
|
||||
void doFinal(byte *digest);
|
||||
/**
|
||||
* Compute the final hash and check it matches this given expected hash
|
||||
*/
|
||||
bool matches(const byte *expected);
|
||||
private:
|
||||
void SHA256_Process(const byte digest[64]);
|
||||
uint32_t total[2];
|
||||
uint32_t state[8];
|
||||
uint8_t buffer[64];
|
||||
};
|
||||
|
||||
#define HMAC_OPAD 0x5C
|
||||
#define HMAC_IPAD 0x36
|
||||
|
||||
/**
|
||||
* Compute a HMAC using SHA256
|
||||
*/
|
||||
class SHA256HMAC
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Compute a SHA256 HMAC with the given [key] key of [length] bytes
|
||||
* for authenticity
|
||||
*/
|
||||
SHA256HMAC(const byte *key, unsigned int keyLen);
|
||||
/**
|
||||
* Update the hash with new data
|
||||
*/
|
||||
void doUpdate(const byte *msg, unsigned int len);
|
||||
void doUpdate(const char *msg, unsigned int len) { doUpdate((byte*) msg, len); }
|
||||
void doUpdate(const char *msg) { doUpdate((byte*) msg, strlen(msg)); }
|
||||
/**
|
||||
* Compute the final hash and store it in [digest], digest must be
|
||||
* at least 32 bytes
|
||||
*/
|
||||
void doFinal(byte *digest);
|
||||
/**
|
||||
* Compute the final hash and check it matches this given expected hash
|
||||
*/
|
||||
bool matches(const byte *expected);
|
||||
private:
|
||||
void blockXor(const byte *in, byte *out, byte val, byte len);
|
||||
SHA256 _hash;
|
||||
byte _innerKey[SHA256HMAC_BLOCKSIZE];
|
||||
byte _outerKey[SHA256HMAC_BLOCKSIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* AES 128 and 256, based on code from axTLS
|
||||
*/
|
||||
class AES
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
AES_MODE_128,
|
||||
AES_MODE_256
|
||||
} AES_MODE;
|
||||
typedef enum
|
||||
{
|
||||
CIPHER_ENCRYPT = 0x01,
|
||||
CIPHER_DECRYPT = 0x02
|
||||
} CIPHER_MODE;
|
||||
|
||||
/**
|
||||
* Create this cipher instance in either encrypt or decrypt mode
|
||||
*
|
||||
* Use the given [key] which must be 16 bytes long for AES 128 and
|
||||
* 32 bytes for AES 256
|
||||
*
|
||||
* Use the given [iv] initialistion vection which must be 16 bytes long
|
||||
*
|
||||
* Use the either AES 128 or AES 256 as specified by [mode]
|
||||
*
|
||||
* Either encrypt or decrypt as specified by [cipherMode]
|
||||
*/
|
||||
AES(const uint8_t *key, const uint8_t *iv, AES_MODE mode, CIPHER_MODE cipherMode);
|
||||
|
||||
/**
|
||||
* Either encrypt or decrypt [in] and store into [out] for [length] bytes, applying no padding
|
||||
*
|
||||
* Note: the length must be a multiple of 16 bytes
|
||||
*/
|
||||
void processNoPad(const uint8_t *in, uint8_t *out, int length);
|
||||
|
||||
/**
|
||||
* Either encrypt or decrypt [in] and store into [out] for [length] bytes, applying padding as needed
|
||||
*
|
||||
* Note: the length must be a multiple of 16 bytes
|
||||
*/
|
||||
void process(const uint8_t *in, uint8_t *out, int length);
|
||||
|
||||
/** Getter method for size
|
||||
*
|
||||
* This function returns the size
|
||||
* @return an integer, that is the size of the of the padded plaintext,
|
||||
* thus, the size of the ciphertext.
|
||||
*/
|
||||
int getSize();
|
||||
|
||||
/** Setter method for size
|
||||
*
|
||||
* This function sets the size of the plaintext+pad
|
||||
*
|
||||
*/
|
||||
void setSize(int size);
|
||||
|
||||
/** Calculates the size of the plaintext and the padding.
|
||||
*
|
||||
* Calculates the size of the plaintext with the size of the
|
||||
* padding needed. Moreover it stores them in their class variables.
|
||||
*
|
||||
* @param in_size the size of the byte array ex sizeof(plaintext)
|
||||
* @return an int the size of the plaintext plus the padding
|
||||
*/
|
||||
int calcSizeAndPad(int in_size);
|
||||
|
||||
/** Pads the plaintext
|
||||
*
|
||||
* This function pads the plaintext and returns an char array with the
|
||||
* plaintext and the padding in order for the plaintext to be compatible with
|
||||
* 16bit size blocks required by AES
|
||||
*
|
||||
* @param in the string of the plaintext in a byte array
|
||||
* @param out The string of the out array.
|
||||
* @return no return, The padded plaintext is stored in the out pointer.
|
||||
*/
|
||||
void padPlaintext(const uint8_t* in, uint8_t* out);
|
||||
|
||||
/** Check the if the padding is correct.
|
||||
*
|
||||
* This functions checks the padding of the plaintext.
|
||||
*
|
||||
* @param in the string of the plaintext in a byte array
|
||||
* @param size the size of the string
|
||||
* @return true if correct / false if not
|
||||
*/
|
||||
bool checkPad(uint8_t* in, int lsize);
|
||||
|
||||
private:
|
||||
void encryptCBC(const uint8_t *in, uint8_t *out, int length);
|
||||
void decryptCBC(const uint8_t *in, uint8_t *out, int length);
|
||||
void convertKey();
|
||||
void encrypt(uint32_t *data);
|
||||
void decrypt(uint32_t *data);
|
||||
uint16_t _rounds;
|
||||
uint16_t _key_size;
|
||||
uint32_t _ks[(AES_MAXROUNDS+1)*8];
|
||||
uint8_t _iv[AES_IV_SIZE];
|
||||
int _pad_size; // size of padding to add to plaintext
|
||||
int _size; // size of plaintext plus padding to be ciphered
|
||||
uint8_t _arr_pad[15];
|
||||
|
||||
CIPHER_MODE _cipherMode;
|
||||
};
|
||||
|
||||
#if defined ESP8266 || defined ESP32
|
||||
/**
|
||||
* ESP8266 and ESP32 specific true random number generator
|
||||
*/
|
||||
class RNG
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Fill the [dst] array with [length] random bytes
|
||||
*/
|
||||
static void fill(uint8_t *dst, unsigned int length);
|
||||
/**
|
||||
* Get a random byte
|
||||
*/
|
||||
static byte get();
|
||||
/**
|
||||
* Get a 32bit random number
|
||||
*/
|
||||
static uint32_t getLong();
|
||||
private:
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
147
libraries/ESP8266WiFiMesh/src/CryptoInterface.cpp
Normal file
147
libraries/ESP8266WiFiMesh/src/CryptoInterface.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* BearSSL Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
* Rest of this file Copyright (C) 2019 Anders Löfgren
|
||||
*
|
||||
* License (MIT license):
|
||||
*
|
||||
* 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 "CryptoInterface.h"
|
||||
#include "TypeConversionFunctions.h"
|
||||
|
||||
#include <bearssl/bearssl.h>
|
||||
|
||||
namespace CryptoInterface
|
||||
{
|
||||
uint8_t *createBearsslHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, uint8_t *resultArray, size_t resultArrayLength)
|
||||
{
|
||||
assert(1 <= resultArrayLength);
|
||||
|
||||
// Comments mainly from https://www.bearssl.org/apidoc/bearssl__hmac_8h.html
|
||||
|
||||
// HMAC is initialized with a key and an underlying hash function; it then fills a "key context". That context contains the processed key.
|
||||
// With the key context, a HMAC context can be initialized to process the input bytes and obtain the MAC output. The key context is not modified during that process, and can be reused.
|
||||
|
||||
// hashType alternatives: &br_md5_vtable; &br_sha1_vtable; &br_sha224_vtable; &br_sha256_vtable; &br_sha384_vtable; &br_sha512_vtable;
|
||||
// Use SHA256 to create the hash.
|
||||
const br_hash_class *hashType = &br_sha256_vtable;
|
||||
|
||||
br_hmac_key_context keyContext; // Holds general HMAC info
|
||||
br_hmac_context hmacContext; // Holds general HMAC info + specific info for the current message
|
||||
|
||||
// HMAC key context initialisation.
|
||||
// Initialise the key context with the provided hash key, using the hash function identified by hashType. This supports arbitrary key lengths.
|
||||
br_hmac_key_init(&keyContext, hashType, hashKey, hashKeyLength);
|
||||
|
||||
// Initialise a HMAC context with a key context. The key context is unmodified.
|
||||
// Relevant data from the key context is immediately copied; the key context can thus be independently reused, modified or released without impacting this HMAC computation.
|
||||
// An explicit output length can be specified; the actual output length will be the minimum of that value and the natural HMAC output length.
|
||||
// If resultArrayLength is 0, then the natural HMAC output length is selected. The "natural output length" is the output length of the underlying hash function.
|
||||
br_hmac_init(&hmacContext, &keyContext, resultArrayLength);
|
||||
|
||||
// Provide the HMAC context with the data to create a HMAC from.
|
||||
// The provided message.length() bytes are injected as extra input in the HMAC computation incarnated by the hmacContext.
|
||||
// It is acceptable that message.length() is zero, in which case data is ignored (and may be NULL) and this function does nothing.
|
||||
br_hmac_update(&hmacContext, message.c_str(), message.length());
|
||||
|
||||
// Compute the HMAC output.
|
||||
// The destination buffer MUST be large enough to accommodate the result; its length is at most the "natural length" of HMAC (i.e. the output length of the underlying hash function).
|
||||
// The context is NOT modified; further bytes may be processed. Thus, "partial HMAC" values can be efficiently obtained.
|
||||
// Optionally the constant-time version br_hmac_outCT() can be used. More info here: https://www.bearssl.org/constanttime.html .
|
||||
br_hmac_out(&hmacContext, resultArray); // returns size_t outputLength
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
String createBearsslHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, size_t hmacLength)
|
||||
{
|
||||
assert(1 <= hmacLength && hmacLength <= SHA256HMAC_NATURAL_LENGTH);
|
||||
byte hmac[hmacLength];
|
||||
createBearsslHmac(message, hashKey, hashKeyLength, hmac, hmacLength);
|
||||
return uint8ArrayToHexString(hmac, hmacLength);
|
||||
}
|
||||
|
||||
uint8_t *createBearsslHmacCT(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, uint8_t *resultArray, size_t resultArrayLength)
|
||||
{
|
||||
assert(1 <= resultArrayLength);
|
||||
|
||||
// Comments mainly from https://www.bearssl.org/apidoc/bearssl__hmac_8h.html
|
||||
|
||||
// HMAC is initialized with a key and an underlying hash function; it then fills a "key context". That context contains the processed key.
|
||||
// With the key context, a HMAC context can be initialized to process the input bytes and obtain the MAC output. The key context is not modified during that process, and can be reused.
|
||||
|
||||
// hashType alternatives: &br_md5_vtable; &br_sha1_vtable; &br_sha224_vtable; &br_sha256_vtable; &br_sha384_vtable; &br_sha512_vtable;
|
||||
// Use SHA256 to create the hash.
|
||||
const br_hash_class *hashType = &br_sha256_vtable;
|
||||
|
||||
br_hmac_key_context keyContext; // Holds general HMAC info
|
||||
br_hmac_context hmacContext; // Holds general HMAC info + specific info for the current message
|
||||
|
||||
// HMAC key context initialisation.
|
||||
// Initialise the key context with the provided hash key, using the hash function identified by hashType. This supports arbitrary key lengths.
|
||||
br_hmac_key_init(&keyContext, hashType, hashKey, hashKeyLength);
|
||||
|
||||
// Initialise a HMAC context with a key context. The key context is unmodified.
|
||||
// Relevant data from the key context is immediately copied; the key context can thus be independently reused, modified or released without impacting this HMAC computation.
|
||||
// An explicit output length can be specified; the actual output length will be the minimum of that value and the natural HMAC output length.
|
||||
// If resultArrayLength is 0, then the natural HMAC output length is selected. The "natural output length" is the output length of the underlying hash function.
|
||||
br_hmac_init(&hmacContext, &keyContext, resultArrayLength);
|
||||
|
||||
// Provide the HMAC context with the data to create a HMAC from.
|
||||
// The provided message.length() bytes are injected as extra input in the HMAC computation incarnated by the hmacContext.
|
||||
// It is acceptable that message.length() is zero, in which case data is ignored (and may be NULL) and this function does nothing.
|
||||
// No need for br_hmac_update when using constant-time version it seems. If it is used, the data provided to br_hmac_outCT will just be appended.
|
||||
// br_hmac_update(&hmacContext, message.c_str(), message.length());
|
||||
|
||||
// Compute the HMAC output. Assumes message is minimum 0 bytes and maximum 1000 bytes.
|
||||
// As long as this is true, the correct HMAC output is calculated in constant-time. More constant-time info here: https://www.bearssl.org/constanttime.html
|
||||
// Some extra input bytes are processed, then the output is computed.
|
||||
// The extra input consists in the message.length() bytes pointed to by message.c_str(). The message.length() parameter must lie between min_len and max_len (inclusive);
|
||||
// max_len bytes are actually read from data (indicating each data byte can be read multiple times, if message.length() < max_len).
|
||||
// Computing time (and memory access pattern) will not depend upon the data byte contents or the value of len.
|
||||
// The output is written in the resultArray buffer, that MUST be large enough to receive it.
|
||||
// The difference max_len - min_len MUST be less than 2^30 (i.e. about one gigabyte).
|
||||
// This function computes the output properly only if the underlying hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256, SHA-384 or SHA-512).
|
||||
// The provided context is NOT modified.
|
||||
size_t min_len = 0;
|
||||
size_t max_len = 1000;
|
||||
assert(min_len <= message.length() && message.length() <= max_len);
|
||||
br_hmac_outCT(&hmacContext, message.c_str(), message.length(), min_len, max_len, resultArray); // returns size_t outputLength
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
String createBearsslHmacCT(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, size_t hmacLength)
|
||||
{
|
||||
assert(1 <= hmacLength && hmacLength <= SHA256HMAC_NATURAL_LENGTH);
|
||||
byte hmac[hmacLength];
|
||||
createBearsslHmacCT(message, hashKey, hashKeyLength, hmac, hmacLength);
|
||||
return uint8ArrayToHexString(hmac, hmacLength);
|
||||
}
|
||||
|
||||
bool verifyBearsslHmac(const String &message, const String &messageHmac, const uint8_t *hashKey, uint8_t hashKeyLength)
|
||||
{
|
||||
String generatedHmac = createBearsslHmac(message, hashKey, hashKeyLength, messageHmac.length()/2); // We know that each HMAC byte should become 2 String characters due to uint8ArrayToHexString.
|
||||
if(generatedHmac == messageHmac)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
120
libraries/ESP8266WiFiMesh/src/CryptoInterface.h
Normal file
120
libraries/ESP8266WiFiMesh/src/CryptoInterface.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* BearSSL Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
* Rest of this file Copyright (C) 2019 Anders Löfgren
|
||||
*
|
||||
* License (MIT license):
|
||||
*
|
||||
* 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 <Arduino.h>
|
||||
|
||||
#ifndef __MESHCRYPTOINTERFACE_H__
|
||||
#define __MESHCRYPTOINTERFACE_H__
|
||||
|
||||
namespace CryptoInterface
|
||||
{
|
||||
const uint8_t SHA256HMAC_NATURAL_LENGTH = 32;
|
||||
|
||||
/**
|
||||
* Create a SHA256 HMAC from the message, using the provided hashKey. The result will be resultArrayLength bytes long and stored in resultArray.
|
||||
* Uses the BearSSL cryptographic library.
|
||||
*
|
||||
* @param message The string from which to create the HMAC.
|
||||
* @param hashKey The hash key to use when creating the HMAC.
|
||||
* @param hashKeyLength The length of the hash key in bytes.
|
||||
* @param resultArray The array wherein to store the resulting HMAC.
|
||||
* @param resultArrayLength The length of resultArray in bytes. Determines the HMAC length. If resultArrayLength is greater than SHA256HMAC_NATURAL_LENGTH,
|
||||
* the first (lowest index) SHA256HMAC_NATURAL_LENGTH bytes of resultArray will be used for the HMAC.
|
||||
*
|
||||
* @return A pointer to resultArray.
|
||||
*/
|
||||
uint8_t *createBearsslHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, uint8_t *resultArray, size_t resultArrayLength);
|
||||
|
||||
/**
|
||||
* Create a SHA256 HMAC from the message, using the provided hashKey. The result will be hmacLength bytes long and returned as a String in HEX format.
|
||||
* Uses the BearSSL cryptographic library.
|
||||
*
|
||||
* @param message The string from which to create the HMAC.
|
||||
* @param hashKey The hash key to use when creating the HMAC.
|
||||
* @param hashKeyLength The length of the hash key in bytes.
|
||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to 32. Defaults to SHA256HMAC_NATURAL_LENGTH.
|
||||
*
|
||||
* @return A String with the generated HMAC in HEX format.
|
||||
*/
|
||||
String createBearsslHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, size_t hmacLength = SHA256HMAC_NATURAL_LENGTH);
|
||||
|
||||
/**
|
||||
* Create a SHA256 HMAC from the message, using the provided hashKey. The result will be resultArrayLength bytes long and stored in resultArray.
|
||||
* Uses the BearSSL cryptographic library.
|
||||
*
|
||||
* Constant-time version of createBearsslHmac(). More constant-time info here: https://www.bearssl.org/constanttime.html
|
||||
* For small messages, it takes substantially longer time to complete than a normal HMAC (5 ms vs 2 ms in a quick benchmark,
|
||||
* determined by the difference between min and max allowed message length), and it also sets a maximum length that messages can be (set to 1000 bytes here).
|
||||
* Making the fixed max length variable would defeat the whole purpose of using constant-time, and not making it variable would create the wrong HMAC if message size exceeds the maximum.
|
||||
*
|
||||
* Also, HMAC is already partially constant-time. Quoting the link above:
|
||||
* "Hash functions implemented by BearSSL (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) consist in bitwise logical operations and additions on 32-bit or 64-bit words,
|
||||
* naturally yielding constant-time operations. HMAC is naturally as constant-time as the underlying hash function. The size of the MACed data, and the size of the key,
|
||||
* may leak, though; only the contents are protected."
|
||||
*
|
||||
* Thus the non constant-time version is used within the mesh framework instead.
|
||||
*
|
||||
* @param message The string from which to create the HMAC. Min size 0 bytes. Max size 1000 bytes.
|
||||
* @param hashKey The hash key to use when creating the HMAC.
|
||||
* @param hashKeyLength The length of the hash key in bytes.
|
||||
* @param resultArray The array wherein to store the resulting HMAC.
|
||||
* @param resultArrayLength The length of resultArray in bytes. Determines the HMAC length. If resultArrayLength is greater than SHA256HMAC_NATURAL_LENGTH,
|
||||
* the first (lowest index) SHA256HMAC_NATURAL_LENGTH bytes of resultArray will be used for the HMAC.
|
||||
*
|
||||
* @return A pointer to resultArray.
|
||||
*/
|
||||
uint8_t *createBearsslHmacCT(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, uint8_t *resultArray, size_t resultArrayLength);
|
||||
|
||||
/**
|
||||
* Create a SHA256 HMAC from the message, using the provided hashKey. The result will be hmacLength bytes long and returned as a String in HEX format.
|
||||
* Uses the BearSSL cryptographic library.
|
||||
*
|
||||
* Constant-time version of createBearsslHmac(). More constant-time info here: https://www.bearssl.org/constanttime.html
|
||||
* Not used within the mesh framework for reasons outlined in the uint8_t *createBearsslHmacCT() description.
|
||||
*
|
||||
* @param message The string from which to create the HMAC. Min size 0 bytes. Max size 1000 bytes.
|
||||
* @param hashKey The hash key to use when creating the HMAC.
|
||||
* @param hashKeyLength The length of the hash key in bytes.
|
||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to 32. Defaults to SHA256HMAC_NATURAL_LENGTH.
|
||||
*
|
||||
* @return A String with the generated HMAC in HEX format.
|
||||
*/
|
||||
String createBearsslHmacCT(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, size_t hmacLength = SHA256HMAC_NATURAL_LENGTH);
|
||||
|
||||
/**
|
||||
* Verify a SHA256 HMAC which was created from the message using the provided hashKey.
|
||||
* Uses the BearSSL cryptographic library.
|
||||
*
|
||||
* @param message The string from which the HMAC was created.
|
||||
* @param messageHmac A string with the generated HMAC in HEX format. Valid messageHmac.length() is 2 to 64.
|
||||
* @param hashKey The hash key to use when creating the HMAC.
|
||||
* @param hashKeyLength The length of the hash key in bytes.
|
||||
*
|
||||
* @return True if the HMAC is correct. False otherwise.
|
||||
*/
|
||||
bool verifyBearsslHmac(const String &message, const String &messageHmac, const uint8_t *hashKey, uint8_t hashKeyLength);
|
||||
}
|
||||
|
||||
#endif
|
@@ -26,6 +26,7 @@
|
||||
#include "UtilityFunctions.h"
|
||||
#include "TypeConversionFunctions.h"
|
||||
#include "JsonTranslator.h"
|
||||
#include "CryptoInterface.h"
|
||||
|
||||
using EspnowProtocolInterpreter::espnowHashKeyLength;
|
||||
|
||||
@@ -127,7 +128,7 @@ uint64_t EncryptedConnectionData::getOwnSessionKey() const { return _ownSessionK
|
||||
|
||||
uint64_t EncryptedConnectionData::incrementSessionKey(uint64_t sessionKey, const uint8_t *hashKey, uint8_t hashKeyLength)
|
||||
{
|
||||
String hmac = JsonTranslator::createHmac(uint64ToString(sessionKey), hashKey, hashKeyLength);
|
||||
String hmac = CryptoInterface::createBearsslHmac(uint64ToString(sessionKey), hashKey, hashKeyLength);
|
||||
|
||||
/* HMAC truncation should be OK since hmac sha256 is a PRF and we are truncating to the leftmost (MSB) bits.
|
||||
PRF: https://crypto.stackexchange.com/questions/26410/whats-the-gcm-sha-256-of-a-tls-protocol/26434#26434
|
||||
|
@@ -55,7 +55,7 @@ void EncryptedConnectionLog::removeDuration()
|
||||
|
||||
void EncryptedConnectionLog::scheduleForRemoval()
|
||||
{
|
||||
// When we give the connection 0 remaining duration it will be removed during the next performEspnowMaintainance() call.
|
||||
// When we give the connection 0 remaining duration it will be removed during the next performEspnowMaintenance() call.
|
||||
// Duration must be changed before setting the scheduledForRemoval flag to true, since the flag is otherwise cleared.
|
||||
setRemainingDuration(0);
|
||||
setScheduledForRemoval(true);
|
||||
|
@@ -26,7 +26,6 @@ extern "C" {
|
||||
#include "UtilityFunctions.h"
|
||||
#include "MutexTracker.h"
|
||||
#include "JsonTranslator.h"
|
||||
#include "Crypto.h"
|
||||
|
||||
using EspnowProtocolInterpreter::espnowEncryptionKeyLength;
|
||||
using EspnowProtocolInterpreter::espnowHashKeyLength;
|
||||
@@ -99,7 +98,7 @@ void espnowDelay(uint32_t durationMs)
|
||||
while(millis() - startingTime < durationMs)
|
||||
{
|
||||
delay(1);
|
||||
EspnowMeshBackend::performEspnowMaintainance();
|
||||
EspnowMeshBackend::performEspnowMaintenance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +223,7 @@ bool EspnowMeshBackend::latestTransmissionSuccessful()
|
||||
return latestTransmissionSuccessfulBase(latestTransmissionOutcomes());
|
||||
}
|
||||
|
||||
void EspnowMeshBackend::performEspnowMaintainance(uint32_t estimatedMaxDuration)
|
||||
void EspnowMeshBackend::performEspnowMaintenance(uint32_t estimatedMaxDuration)
|
||||
{
|
||||
ExpiringTimeTracker estimatedMaxDurationTracker = ExpiringTimeTracker(estimatedMaxDuration);
|
||||
|
||||
@@ -232,7 +231,7 @@ void EspnowMeshBackend::performEspnowMaintainance(uint32_t estimatedMaxDuration)
|
||||
MutexTracker mutexTracker(_espnowTransmissionMutex, handlePostponedRemovals);
|
||||
if(!mutexTracker.mutexCaptured())
|
||||
{
|
||||
assert(false && "ERROR! Transmission in progress. Don't call performEspnowMaintainance from callbacks as this may corrupt program state! Aborting.");
|
||||
assert(false && "ERROR! Transmission in progress. Don't call performEspnowMaintenance from callbacks as this may corrupt program state! Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -80,7 +80,6 @@
|
||||
#include "MessageData.h"
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "Crypto.h"
|
||||
#include "EspnowNetworkInfo.h"
|
||||
|
||||
typedef enum
|
||||
@@ -111,11 +110,11 @@ typedef enum
|
||||
|
||||
|
||||
/**
|
||||
* An alternative to standard delay(). Will continuously call performEspnowMaintainance() during the waiting time, so that the ESP-NOW node remains responsive.
|
||||
* An alternative to standard delay(). Will continuously call performEspnowMaintenance() during the waiting time, so that the ESP-NOW node remains responsive.
|
||||
* Note that if there is a lot of ESP-NOW transmission activity to the node during the espnowDelay, the desired duration may be overshot by several ms.
|
||||
* Thus, if precise timing is required, use standard delay() instead.
|
||||
*
|
||||
* Should not be used inside responseHandler, requestHandler, networkFilter or broadcastFilter callbacks since performEspnowMaintainance() can alter the ESP-NOW state.
|
||||
* Should not be used inside responseHandler, requestHandler, networkFilter or broadcastFilter callbacks since performEspnowMaintenance() can alter the ESP-NOW state.
|
||||
*
|
||||
* @param durationMs The shortest allowed delay duration, in milliseconds.
|
||||
*/
|
||||
@@ -202,15 +201,15 @@ public:
|
||||
* It is recommended to place it in the beginning of the loop(), unless there is a need to put it elsewhere.
|
||||
* Among other things, the method cleans up old Espnow log entries (freeing up RAM) and sends the responses you provide to Espnow requests.
|
||||
* Note that depending on the amount of responses to send and their length, this method can take tens or even hundreds of milliseconds to complete.
|
||||
* More intense transmission activity and less frequent calls to performEspnowMaintainance will likely cause the method to take longer to complete, so plan accordingly.
|
||||
* More intense transmission activity and less frequent calls to performEspnowMaintenance will likely cause the method to take longer to complete, so plan accordingly.
|
||||
*
|
||||
* Should not be used inside responseHandler, requestHandler, networkFilter or broadcastFilter callbacks since performEspnowMaintainance() can alter the ESP-NOW state.
|
||||
* Should not be used inside responseHandler, requestHandler, networkFilter or broadcastFilter callbacks since performEspnowMaintenance() can alter the ESP-NOW state.
|
||||
*
|
||||
* @param estimatedMaxDuration The desired max duration for the method. If set to 0 there is no duration limit.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintainance.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintenance.
|
||||
* Also note that although the method will try to respect the max duration limit, there is no guarantee. Overshoots by tens of milliseconds are possible.
|
||||
*/
|
||||
static void performEspnowMaintainance(uint32_t estimatedMaxDuration = 0);
|
||||
static void performEspnowMaintenance(uint32_t estimatedMaxDuration = 0);
|
||||
|
||||
/**
|
||||
* At critical heap level no more incoming requests are accepted.
|
||||
@@ -703,19 +702,19 @@ protected:
|
||||
* For example, response order will be mixed up if some responses fail to transmit while others transmit successfully.
|
||||
*
|
||||
* @param estimatedMaxDurationTracker A pointer to an ExpiringTimeTracker initialized with the desired max duration for the method. If set to nullptr there is no duration limit.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintainance.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintenance.
|
||||
* Also note that although the method will try to respect the max duration limit, there is no guarantee. Overshoots by tens of milliseconds are possible.
|
||||
*/
|
||||
static void sendStoredEspnowMessages(const ExpiringTimeTracker *estimatedMaxDurationTracker = nullptr);
|
||||
/*
|
||||
* @param estimatedMaxDurationTracker A pointer to an ExpiringTimeTracker initialized with the desired max duration for the method. If set to nullptr there is no duration limit.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintainance.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintenance.
|
||||
* Also note that although the method will try to respect the max duration limit, there is no guarantee. Overshoots by tens of milliseconds are possible.
|
||||
*/
|
||||
static void sendPeerRequestConfirmations(const ExpiringTimeTracker *estimatedMaxDurationTracker = nullptr);
|
||||
/*
|
||||
* @param estimatedMaxDurationTracker A pointer to an ExpiringTimeTracker initialized with the desired max duration for the method. If set to nullptr there is no duration limit.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintainance.
|
||||
* Note that setting the estimatedMaxDuration too low may result in missed ESP-NOW transmissions because of too little time for maintenance.
|
||||
* Also note that although the method will try to respect the max duration limit, there is no guarantee. Overshoots by tens of milliseconds are possible.
|
||||
*/
|
||||
static void sendEspnowResponses(const ExpiringTimeTracker *estimatedMaxDurationTracker = nullptr);
|
||||
|
@@ -37,7 +37,7 @@ void floodingMeshDelay(uint32_t durationMs)
|
||||
while(millis() - startingTime < durationMs)
|
||||
{
|
||||
delay(1);
|
||||
FloodingMesh::performMeshMaintainance();
|
||||
FloodingMesh::performMeshMaintenance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,25 +74,25 @@ void FloodingMesh::begin()
|
||||
// Initialise the mesh node
|
||||
getEspnowMeshBackend().begin();
|
||||
|
||||
// Makes it possible to find the node through scans, and also makes it possible to recover from an encrypted ESP-NOW connection where only the other node is encrypted.
|
||||
// Note that only one AP can be active at a time in total, and this will always be the one which was last activated.
|
||||
// Thus the AP is shared by all backends.
|
||||
getEspnowMeshBackend().activateAP();
|
||||
|
||||
availableFloodingMeshes.insert(this); // Returns std::pair<iterator,bool>
|
||||
}
|
||||
|
||||
void FloodingMesh::performMeshMaintainance()
|
||||
void FloodingMesh::activateAP()
|
||||
{
|
||||
getEspnowMeshBackend().activateAP();
|
||||
}
|
||||
|
||||
void FloodingMesh::performMeshMaintenance()
|
||||
{
|
||||
for(FloodingMesh *meshInstance : availableFloodingMeshes)
|
||||
{
|
||||
meshInstance->performMeshInstanceMaintainance();
|
||||
meshInstance->performMeshInstanceMaintenance();
|
||||
}
|
||||
}
|
||||
|
||||
void FloodingMesh::performMeshInstanceMaintainance()
|
||||
void FloodingMesh::performMeshInstanceMaintenance()
|
||||
{
|
||||
EspnowMeshBackend::performEspnowMaintainance();
|
||||
EspnowMeshBackend::performEspnowMaintenance();
|
||||
|
||||
for(std::list<std::pair<String, bool>>::iterator backlogIterator = _forwardingBacklog.begin(); backlogIterator != _forwardingBacklog.end(); )
|
||||
{
|
||||
@@ -110,7 +110,7 @@ void FloodingMesh::performMeshInstanceMaintainance()
|
||||
|
||||
backlogIterator = _forwardingBacklog.erase(backlogIterator);
|
||||
|
||||
EspnowMeshBackend::performEspnowMaintainance(); // It is best to performEspnowMaintainance frequently to keep the Espnow backend responsive. Especially if each encryptedBroadcast takes a lot of time.
|
||||
EspnowMeshBackend::performEspnowMaintenance(); // It is best to performEspnowMaintenance frequently to keep the Espnow backend responsive. Especially if each encryptedBroadcast takes a lot of time.
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -31,11 +31,11 @@
|
||||
#include <queue>
|
||||
|
||||
/**
|
||||
* An alternative to standard delay(). Will continuously call performMeshMaintainance() during the waiting time, so that the FloodingMesh node remains responsive.
|
||||
* An alternative to standard delay(). Will continuously call performMeshMaintenance() during the waiting time, so that the FloodingMesh node remains responsive.
|
||||
* Note that if there is a lot of FloodingMesh transmission activity to the node during the floodingMeshDelay, the desired duration may be overshot by several ms.
|
||||
* Thus, if precise timing is required, use standard delay() instead.
|
||||
*
|
||||
* Should not be used inside callbacks since performMeshMaintainance() can alter the ESP-NOW state.
|
||||
* Should not be used inside callbacks since performMeshMaintenance() can alter the ESP-NOW state.
|
||||
*
|
||||
* @param durationMs The shortest allowed delay duration, in milliseconds.
|
||||
*/
|
||||
@@ -92,16 +92,25 @@ public:
|
||||
* All FloodingMesh instances can still broadcast messages though, even if their AP is not visible.
|
||||
*/
|
||||
void begin();
|
||||
|
||||
/**
|
||||
* Makes it possible to find the node through scans, and also makes it possible to recover from an encrypted ESP-NOW connection where only the other node is encrypted.
|
||||
* Required for encryptedBroadcast() usage, but also slows down the start-up of the node.
|
||||
*
|
||||
* Note that only one AP can be active at a time in total, and this will always be the one which was last activated.
|
||||
* Thus the AP is shared by all backends.
|
||||
*/
|
||||
void activateAP();
|
||||
|
||||
/**
|
||||
* Performs maintainance for all available Flooding Mesh instances
|
||||
* Performs maintenance for all available Flooding Mesh instances
|
||||
*/
|
||||
static void performMeshMaintainance();
|
||||
static void performMeshMaintenance();
|
||||
|
||||
/**
|
||||
* Performs maintainance for this particular Flooding Mesh instance
|
||||
* Performs maintenance for this particular Flooding Mesh instance
|
||||
*/
|
||||
void performMeshInstanceMaintainance();
|
||||
void performMeshInstanceMaintenance();
|
||||
|
||||
/**
|
||||
* Serialize the current mesh node state. Useful to save a state before the node goes to sleep.
|
||||
|
@@ -23,9 +23,9 @@
|
||||
*/
|
||||
|
||||
#include "JsonTranslator.h"
|
||||
#include "Crypto.h"
|
||||
#include "EspnowProtocolInterpreter.h"
|
||||
#include "TypeConversionFunctions.h"
|
||||
#include "CryptoInterface.h"
|
||||
|
||||
namespace JsonTranslator
|
||||
{
|
||||
@@ -39,59 +39,6 @@ namespace JsonTranslator
|
||||
return valueIdentifier + "\"" + value + "\"}}";
|
||||
}
|
||||
|
||||
uint8_t *createHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, uint8_t resultArray[SHA256HMAC_SIZE])
|
||||
{
|
||||
// Create the HMAC instance with our key
|
||||
SHA256HMAC hmac(hashKey, hashKeyLength);
|
||||
|
||||
// Update the HMAC with our message
|
||||
hmac.doUpdate(message.c_str());
|
||||
|
||||
// Finish the HMAC calculation and return the authentication code
|
||||
hmac.doFinal(resultArray);
|
||||
|
||||
// resultArray now contains our SHA256HMAC_SIZE byte authentication code
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
String createHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength)
|
||||
{
|
||||
byte hmac[SHA256HMAC_SIZE];
|
||||
createHmac(message, hashKey, hashKeyLength, hmac);
|
||||
return uint8ArrayToHexString(hmac, SHA256HMAC_SIZE);
|
||||
}
|
||||
|
||||
bool verifyHmac(const String &message, const String &messageHmac, const uint8_t *hashKey, uint8_t hashKeyLength)
|
||||
{
|
||||
if(messageHmac.length() != 2*SHA256HMAC_SIZE) // We know that each HMAC byte should become 2 String characters due to uint8ArrayToHexString.
|
||||
return false;
|
||||
|
||||
String generatedHmac = createHmac(message, hashKey, hashKeyLength);
|
||||
if(generatedHmac == messageHmac)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool verifyEncryptionRequestHmac(const String &encryptionRequestHmacMessage, const uint8_t *requesterStaMac, const uint8_t *requesterApMac,
|
||||
const uint8_t *hashKey, uint8_t hashKeyLength)
|
||||
{
|
||||
String hmac = "";
|
||||
if(getHmac(encryptionRequestHmacMessage, hmac))
|
||||
{
|
||||
int32_t hmacStartIndex = encryptionRequestHmacMessage.indexOf(jsonHmac);
|
||||
if(hmacStartIndex < 0)
|
||||
return false;
|
||||
|
||||
if(verifyHmac(macToString(requesterStaMac) + macToString(requesterApMac) + encryptionRequestHmacMessage.substring(0, hmacStartIndex), hmac, hashKey, hashKeyLength))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String createEncryptedConnectionInfo(const String &infoHeader, const String &requestNonce, const String &authenticationPassword, uint64_t ownSessionKey, uint64_t peerSessionKey)
|
||||
{
|
||||
// Returns: Encrypted connection info:{"arguments":{"nonce":"1F2","password":"abc","ownSK":"3B4","peerSK":"1A2"}}
|
||||
@@ -122,9 +69,31 @@ namespace JsonTranslator
|
||||
uint8_t staMac[6] {0};
|
||||
uint8_t apMac[6] {0};
|
||||
String requesterStaApMac = macToString(WiFi.macAddress(staMac)) + macToString(WiFi.softAPmacAddress(apMac));
|
||||
String hmac = createHmac(requesterStaApMac + mainMessage, hashKey, hashKeyLength);
|
||||
String hmac = CryptoInterface::createBearsslHmac(requesterStaApMac + mainMessage, hashKey, hashKeyLength);
|
||||
return mainMessage + createJsonEndPair(jsonHmac, hmac);
|
||||
}
|
||||
|
||||
bool verifyEncryptionRequestHmac(const String &encryptionRequestHmacMessage, const uint8_t *requesterStaMac, const uint8_t *requesterApMac,
|
||||
const uint8_t *hashKey, uint8_t hashKeyLength)
|
||||
{
|
||||
using namespace CryptoInterface;
|
||||
|
||||
String hmac = "";
|
||||
if(getHmac(encryptionRequestHmacMessage, hmac))
|
||||
{
|
||||
int32_t hmacStartIndex = encryptionRequestHmacMessage.indexOf(jsonHmac);
|
||||
if(hmacStartIndex < 0)
|
||||
return false;
|
||||
|
||||
if(hmac.length() == 2*SHA256HMAC_NATURAL_LENGTH // We know that each HMAC byte should become 2 String characters due to uint8ArrayToHexString.
|
||||
&& verifyBearsslHmac(macToString(requesterStaMac) + macToString(requesterApMac) + encryptionRequestHmacMessage.substring(0, hmacStartIndex), hmac, hashKey, hashKeyLength))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t getStartIndex(const String &jsonString, const String &valueIdentifier, int32_t searchStartIndex)
|
||||
{
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#define __ESPNOWJSONTRANSLATOR_H__
|
||||
|
||||
#include <WString.h>
|
||||
#include "Crypto.h"
|
||||
|
||||
namespace JsonTranslator
|
||||
{
|
||||
@@ -45,18 +44,14 @@ namespace JsonTranslator
|
||||
|
||||
String createJsonPair(const String &valueIdentifier, const String &value);
|
||||
String createJsonEndPair(const String &valueIdentifier, const String &value);
|
||||
|
||||
uint8_t *createHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength, uint8_t resultArray[SHA256HMAC_SIZE]);
|
||||
String createHmac(const String &message, const uint8_t *hashKey, uint8_t hashKeyLength);
|
||||
|
||||
bool verifyHmac(const String &message, const String &messageHmac, const uint8_t *hashKey, uint8_t hashKeyLength);
|
||||
bool verifyEncryptionRequestHmac(const String &encryptionRequestHmacMessage, const uint8_t *requesterStaMac, const uint8_t *requesterApMac, const uint8_t *hashKey, uint8_t hashKeyLength);
|
||||
|
||||
String createEncryptedConnectionInfo(const String &infoHeader, const String &requestNonce, const String &authenticationPassword, uint64_t ownSessionKey, uint64_t peerSessionKey);
|
||||
String createEncryptionRequestIntro(const String &requestHeader, uint32_t duration = 0);
|
||||
String createEncryptionRequestEnding(const String &requestNonce);
|
||||
String createEncryptionRequestHmacMessage(const String &requestHeader, const String &requestNonce, const uint8_t *hashKey, uint8_t hashKeyLength, uint32_t duration = 0);
|
||||
|
||||
bool verifyEncryptionRequestHmac(const String &encryptionRequestHmacMessage, const uint8_t *requesterStaMac, const uint8_t *requesterApMac, const uint8_t *hashKey, uint8_t hashKeyLength);
|
||||
|
||||
/**
|
||||
* Provides the index within jsonString where the value of valueIdentifier starts.
|
||||
*
|
||||
|
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "TypeConversionFunctions.h"
|
||||
#include "Crypto.h"
|
||||
|
||||
String uint64ToString(uint64_t number, byte base)
|
||||
{
|
||||
|
Reference in New Issue
Block a user