-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* - Add CryptoInterface library. - Add TypeConversion core files. * Fix compiler errors. - Make HelloCrypto.ino stylish. - Include assert.h in CryptoInterface.cpp. * - Move base36 arrays to PROGMEM in TypeConversionFunctions.cpp. - Add deprecated attribute to SHA1 and MD5 hashes. - Remove _warningsEnabled since this has been replaced by the deprecated attribute. - Prefix all getters with "get". - Move all CryptoInterface functionality to the experimental namespace. - Change formatting of core files. - Improve comments. * - Update keywords.txt. * - Remove WiFi.disconnect() from setup() in HelloCrypto example since it no longer seems to be required. * - Classify everything. - Remove delay in setup() from HelloCrypto example since it does not seem to be required to prevent missing initial Serial prints. - Mark type conversion functions as big endian. - Update keywords.txt. * - Remove namespace experimental. - Create ESP.random functions in the core based on the defaultNonceGenerator code, and use these in defaultNonceGenerator. - Rename CryptoInterface to esp8266::Crypto and move all functionality to the core. - Remove need to #include <bearssl/bearssl.h> in the Crypto header file by changing br_hkdf_context to ::br_hkdf_context. - Restyle code files for core usage. * - Re-add namespace experimental. - Improve comments. * - Remove namespace esp8266. - Rename namespace Crypto to namespace crypto. Co-authored-by: Anders <andlo151@student.liu.se> Co-authored-by: Develo <deveyes@gmail.com>
- Loading branch information
1 parent
ec76442
commit 3c9a75f
Showing
9 changed files
with
1,757 additions
and
1 deletion.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
TypeConversion functionality | ||
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 <assert.h> | ||
#include "TypeConversion.h" | ||
|
||
namespace esp8266 | ||
{ | ||
namespace TypeConversion | ||
{ | ||
const char base36Chars[36] PROGMEM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; | ||
const uint8_t base36CharValues[75] PROGMEM {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, // 0 to 9 | ||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, // Upper case letters | ||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 // Lower case letters | ||
}; | ||
|
||
|
||
String uint8ArrayToHexString(const uint8_t *uint8Array, const uint32_t arrayLength) | ||
{ | ||
String hexString; | ||
if (!hexString.reserve(2 * arrayLength)) // Each uint8_t will become two characters (00 to FF) | ||
{ | ||
return emptyString; | ||
} | ||
|
||
for (uint32_t i = 0; i < arrayLength; ++i) | ||
{ | ||
hexString += (char)pgm_read_byte(base36Chars + (uint8Array[i] >> 4)); | ||
hexString += (char)pgm_read_byte(base36Chars + uint8Array[i] % 16); | ||
} | ||
|
||
return hexString; | ||
} | ||
|
||
uint8_t *hexStringToUint8Array(const String &hexString, uint8_t *uint8Array, const uint32_t arrayLength) | ||
{ | ||
assert(hexString.length() >= arrayLength * 2); // Each array element can hold two hexString characters | ||
|
||
for (uint32_t i = 0; i < arrayLength; ++i) | ||
{ | ||
uint8Array[i] = (pgm_read_byte(base36CharValues + hexString.charAt(i * 2) - '0') << 4) + pgm_read_byte(base36CharValues + hexString.charAt(i * 2 + 1) - '0'); | ||
} | ||
|
||
return uint8Array; | ||
} | ||
|
||
uint8_t *uint64ToUint8ArrayBE(const uint64_t value, uint8_t *resultArray) | ||
{ | ||
resultArray[7] = value; | ||
resultArray[6] = value >> 8; | ||
resultArray[5] = value >> 16; | ||
resultArray[4] = value >> 24; | ||
resultArray[3] = value >> 32; | ||
resultArray[2] = value >> 40; | ||
resultArray[1] = value >> 48; | ||
resultArray[0] = value >> 56; | ||
|
||
return resultArray; | ||
} | ||
|
||
uint64_t uint8ArrayToUint64BE(const uint8_t *inputArray) | ||
{ | ||
uint64_t result = (uint64_t)inputArray[0] << 56 | (uint64_t)inputArray[1] << 48 | (uint64_t)inputArray[2] << 40 | (uint64_t)inputArray[3] << 32 | ||
| (uint64_t)inputArray[4] << 24 | (uint64_t)inputArray[5] << 16 | (uint64_t)inputArray[6] << 8 | (uint64_t)inputArray[7]; | ||
|
||
return result; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
TypeConversion functionality | ||
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. | ||
*/ | ||
|
||
#ifndef __ESP8266_TYPECONVERSION_H__ | ||
#define __ESP8266_TYPECONVERSION_H__ | ||
|
||
#include <Arduino.h> | ||
|
||
namespace esp8266 | ||
{ | ||
namespace TypeConversion | ||
{ | ||
extern const char base36Chars[36]; | ||
|
||
// Subtract '0' to normalize the char before lookup. | ||
extern const uint8_t base36CharValues[75]; | ||
|
||
/** | ||
Convert the contents of a uint8_t array to a String in HEX format. The resulting String starts from index 0 of the array. | ||
All array elements will be padded with zeroes to ensure they are converted to 2 String characters each. | ||
@param uint8Array The array to make into a HEX String. | ||
@param arrayLength The size of uint8Array, in bytes. | ||
@return Normally a String containing the HEX representation of the uint8Array. An empty String if the memory allocation for the String failed. | ||
*/ | ||
String uint8ArrayToHexString(const uint8_t *uint8Array, const uint32_t arrayLength); | ||
|
||
/** | ||
Convert the contents of a String in HEX format to a uint8_t array. Index 0 of the array will represent the start of the String. | ||
There must be 2 String characters for each array element. Use padding with zeroes where required. | ||
@param hexString The HEX String to convert to a uint8_t array. Must contain at least 2*arrayLength characters. | ||
@param uint8Array The array to fill with the contents of the hexString. | ||
@param arrayLength The number of bytes to fill in uint8Array. | ||
@return A pointer to the uint8Array. | ||
*/ | ||
uint8_t *hexStringToUint8Array(const String &hexString, uint8_t *uint8Array, const uint32_t arrayLength); | ||
|
||
/** | ||
Takes a uint64_t value and stores the bits in a uint8_t array. Assumes index 0 of the array should contain MSB (big endian). | ||
@param value The uint64_t value to convert to a uint8_t array. | ||
@param resultArray A uint8_t array that will hold the result once the function returns. Should have a size of at least 8 bytes. | ||
@return The resultArray. | ||
*/ | ||
uint8_t *uint64ToUint8ArrayBE(const uint64_t value, uint8_t *resultArray); | ||
|
||
/** | ||
Takes a uint8_t array and converts the first 8 (lowest index) elements to a uint64_t. Assumes index 0 of the array contains MSB (big endian). | ||
@param inputArray A uint8_t array containing the data to convert to a uint64_t. Should have a size of at least 8 bytes. | ||
@return A uint64_t representation of the first 8 bytes of the array. | ||
*/ | ||
uint64_t uint8ArrayToUint64BE(const uint8_t *inputArray); | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/** | ||
This example demonstrates the usage of the ESP8266 Crypto implementation, which aims to contain easy-to-use cryptographic functions. | ||
Crypto is currently primarily a frontend for the cryptographic library BearSSL which is used by `BearSSL::WiFiClientSecure` and `BearSSL::WiFiServerSecure` in the ESP8266 Arduino Core. | ||
Extensive documentation can be found in the Crypto source code files and on the [BearSSL homepage](https://www.bearssl.org). | ||
*/ | ||
|
||
#include <ESP8266WiFi.h> | ||
#include <TypeConversion.h> | ||
#include <Crypto.h> | ||
|
||
namespace TypeCast = esp8266::TypeConversion; | ||
using namespace experimental; | ||
|
||
/** | ||
NOTE: Although we could define the strings below as normal String variables, | ||
here we are using PROGMEM combined with the FPSTR() macro (and also just the F() macro further down in the file). | ||
The reason is that this approach will place the strings in flash memory which will help save RAM during program execution. | ||
Reading strings from flash will be slower than reading them from RAM, | ||
but this will be a negligible difference when printing them to Serial. | ||
More on F(), FPSTR() and PROGMEM: | ||
https://github.com/esp8266/Arduino/issues/1143 | ||
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html | ||
*/ | ||
constexpr char masterKey[] PROGMEM = "w86vn@rpfA O+S"; // Use 8 random characters or more | ||
|
||
void setup() { | ||
// Prevents the flash memory from being worn out, see: https://github.com/esp8266/Arduino/issues/1054 . | ||
// This will however delay node WiFi start-up by about 700 ms. The delay is 900 ms if we otherwise would have stored the WiFi network we want to connect to. | ||
WiFi.persistent(false); | ||
|
||
Serial.begin(115200); | ||
|
||
Serial.println(); | ||
Serial.println(); | ||
} | ||
|
||
void loop() { | ||
// This serves only to demonstrate the library use. See the header file for a full list of functions. | ||
|
||
String exampleData = F("Hello Crypto World!"); | ||
Serial.println(String(F("This is our example data: ")) + exampleData); | ||
|
||
uint8_t resultArray[crypto::SHA256::NATURAL_LENGTH] { 0 }; | ||
uint8_t derivedKey[crypto::ENCRYPTION_KEY_LENGTH] { 0 }; | ||
|
||
static uint32_t encryptionCounter = 0; | ||
|
||
|
||
// Generate the salt to use for HKDF | ||
uint8_t hkdfSalt[16] { 0 }; | ||
crypto::getNonceGenerator()(hkdfSalt, sizeof hkdfSalt); | ||
|
||
// Generate the key to use for HMAC and encryption | ||
crypto::HKDF hkdfInstance(FPSTR(masterKey), (sizeof masterKey) - 1, hkdfSalt, sizeof hkdfSalt); // (sizeof masterKey) - 1 removes the terminating null value of the c-string | ||
hkdfInstance.produce(derivedKey, sizeof derivedKey); | ||
|
||
// Hash | ||
crypto::SHA256::hash(exampleData.c_str(), exampleData.length(), resultArray); | ||
Serial.println(String(F("\nThis is the SHA256 hash of our example data, in HEX format:\n")) + TypeCast::uint8ArrayToHexString(resultArray, sizeof resultArray)); | ||
Serial.println(String(F("This is the SHA256 hash of our example data, in HEX format, using String output:\n")) + crypto::SHA256::hash(exampleData)); | ||
|
||
|
||
// HMAC | ||
// Note that HMAC output length is limited | ||
crypto::SHA256::hmac(exampleData.c_str(), exampleData.length(), derivedKey, sizeof derivedKey, resultArray, sizeof resultArray); | ||
Serial.println(String(F("\nThis is the SHA256 HMAC of our example data, in HEX format:\n")) + TypeCast::uint8ArrayToHexString(resultArray, sizeof resultArray)); | ||
Serial.println(String(F("This is the SHA256 HMAC of our example data, in HEX format, using String output:\n")) + crypto::SHA256::hmac(exampleData, derivedKey, sizeof derivedKey, crypto::SHA256::NATURAL_LENGTH)); | ||
|
||
|
||
// Authenticated Encryption with Associated Data (AEAD) | ||
String dataToEncrypt = F("This data is not encrypted."); | ||
uint8_t resultingNonce[12] { 0 }; // The nonce is always 12 bytes | ||
uint8_t resultingTag[16] { 0 }; // The tag is always 16 bytes | ||
|
||
Serial.println(String(F("\nThis is the data to encrypt: ")) + dataToEncrypt); | ||
|
||
// Note that the key must be ENCRYPTION_KEY_LENGTH long. | ||
crypto::ChaCha20Poly1305::encrypt(dataToEncrypt.begin(), dataToEncrypt.length(), derivedKey, &encryptionCounter, sizeof encryptionCounter, resultingNonce, resultingTag); | ||
Serial.println(String(F("Encrypted data: ")) + dataToEncrypt); | ||
|
||
bool decryptionSucceeded = crypto::ChaCha20Poly1305::decrypt(dataToEncrypt.begin(), dataToEncrypt.length(), derivedKey, &encryptionCounter, sizeof encryptionCounter, resultingNonce, resultingTag); | ||
encryptionCounter++; | ||
|
||
if (decryptionSucceeded) { | ||
Serial.print(F("Decryption succeeded. Result: ")); | ||
} else { | ||
Serial.print(F("Decryption failed. Result: ")); | ||
} | ||
|
||
Serial.println(dataToEncrypt); | ||
|
||
|
||
Serial.println(F("\n##########################################################################################################\n")); | ||
|
||
delay(10000); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.