-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Add CryptoInterface library #6961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
b3362a0
- Add CryptoInterface library.
aerlon 2151f7a
Merge branch 'master' into crypto_interface
aerlon 6a448bc
Fix compiler errors.
aerlon b1fc47a
- Move base36 arrays to PROGMEM in TypeConversionFunctions.cpp.
aerlon 92dd1a2
Merge branch 'master' into crypto_interface
aerlon 9e5b63f
- Update keywords.txt.
aerlon c09252e
Merge branch 'master' into crypto_interface
devyte efb11c1
- Remove WiFi.disconnect() from setup() in HelloCrypto example since …
aerlon 884113b
- Classify everything.
aerlon 77c5d8d
Merge branch 'master' into crypto_interface
aerlon ef86d20
- Remove namespace experimental.
aerlon f1783e0
- Re-add namespace experimental.
aerlon 7f0324c
- Remove namespace esp8266.
aerlon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 *uint64ToUint8Array(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 uint8ArrayToUint64(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 | ||
aerlon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| (uint64_t)inputArray[4] << 24 | (uint64_t)inputArray[5] << 16 | (uint64_t)inputArray[6] << 8 | (uint64_t)inputArray[7]; | ||
|
||
return result; | ||
} | ||
} | ||
} |
This file contains hidden or 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. | ||
|
||
@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 *uint64ToUint8Array(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. | ||
|
||
@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 uint8ArrayToUint64(const uint8_t *inputArray); | ||
} | ||
} | ||
|
||
#endif |
This file contains hidden or 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,9 @@ | ||
ESP8266 CryptoInterface | ||
================= | ||
|
||
A library containing easy-to-use cryptographic functions. Primarily a frontend for the cryptographic library BearSSL which is used by `BearSSL::WiFiClientSecure` and `BearSSL::WiFiServerSecure` in the ESP8266 Arduino Core. | ||
|
||
Usage | ||
----- | ||
|
||
There are a number of cryptographic functions in the library. See the included example for a guide on how to use some of them. Extensive documentation can be found in the library source code files and on the [BearSSL homepage](https://www.bearssl.org). |
102 changes: 102 additions & 0 deletions
102
libraries/CryptoInterface/examples/HelloCrypto/HelloCrypto.ino
This file contains hidden or 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,102 @@ | ||
/** | ||
This example shows the functionality of the CryptoInterface library. | ||
*/ | ||
|
||
#include <ESP8266WiFi.h> | ||
#include <TypeConversion.h> | ||
#include <CryptoInterface.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); | ||
delay(50); // Wait for Serial. | ||
aerlon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
//yield(); // Use this if you don't want to wait for Serial. | ||
|
||
// The WiFi.disconnect() ensures that the WiFi is working correctly. If this is not done before receiving WiFi connections, | ||
// those WiFi connections will take a long time to make or sometimes will not work at all. | ||
aerlon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
WiFi.disconnect(); | ||
|
||
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[CryptoInterface::SHA256_NATURAL_LENGTH] { 0 }; | ||
uint8_t derivedKey[CryptoInterface::ENCRYPTION_KEY_LENGTH] { 0 }; | ||
|
||
static uint32_t encryptionCounter = 0; | ||
|
||
|
||
// Generate the salt to use for HKDF | ||
uint8_t hkdfSalt[16] { 0 }; | ||
CryptoInterface::getNonceGenerator()(hkdfSalt, sizeof hkdfSalt); | ||
|
||
// Generate the key to use for HMAC and encryption | ||
CryptoInterface::hkdfInit(FPSTR(masterKey), (sizeof masterKey) - 1, hkdfSalt, sizeof hkdfSalt); // (sizeof masterKey) - 1 removes the terminating null value of the c-string | ||
CryptoInterface::hkdfProduce(derivedKey, sizeof derivedKey); | ||
|
||
// Hash | ||
CryptoInterface::sha256Hash(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")) + CryptoInterface::sha256Hash(exampleData)); | ||
|
||
|
||
// HMAC | ||
// Note that HMAC output length is limited | ||
CryptoInterface::sha256Hmac(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")) + CryptoInterface::sha256Hmac(exampleData, derivedKey, sizeof derivedKey, CryptoInterface::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. | ||
CryptoInterface::chacha20Poly1305Encrypt(dataToEncrypt.begin(), dataToEncrypt.length(), derivedKey, &encryptionCounter, sizeof encryptionCounter, resultingNonce, resultingTag); | ||
Serial.println(String(F("Encrypted data: ")) + dataToEncrypt); | ||
|
||
bool decryptionSucceeded = CryptoInterface::chacha20Poly1305Decrypt(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 hidden or 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,63 @@ | ||
####################################### | ||
# Syntax Coloring Map For CryptoInterface | ||
####################################### | ||
|
||
####################################### | ||
# Library (KEYWORD3) | ||
####################################### | ||
|
||
CryptoInterface KEYWORD3 | ||
|
||
####################################### | ||
# Datatypes (KEYWORD1) | ||
####################################### | ||
|
||
nonceGeneratorType KEYWORD1 | ||
|
||
####################################### | ||
# Methods and Functions (KEYWORD2) | ||
####################################### | ||
|
||
setCtMinDataLength KEYWORD2 | ||
getCtMinDataLength KEYWORD2 | ||
setCtMaxDataLength KEYWORD2 | ||
getCtMaxDataLength KEYWORD2 | ||
setNonceGenerator KEYWORD2 | ||
getNonceGenerator KEYWORD2 | ||
md5Hash KEYWORD2 | ||
md5Hmac KEYWORD2 | ||
md5HmacCT KEYWORD2 | ||
sha1Hash KEYWORD2 | ||
sha1Hmac KEYWORD2 | ||
sha1HmacCT KEYWORD2 | ||
sha224Hash KEYWORD2 | ||
sha224Hmac KEYWORD2 | ||
sha224HmacCT KEYWORD2 | ||
sha256Hash KEYWORD2 | ||
sha256Hmac KEYWORD2 | ||
sha256HmacCT KEYWORD2 | ||
sha384Hash KEYWORD2 | ||
sha384Hmac KEYWORD2 | ||
sha384HmacCT KEYWORD2 | ||
sha512Hash->KEYWORD2 | ||
sha512Hmac KEYWORD2 | ||
sha512HmacCT KEYWORD2 | ||
md5sha1Hash KEYWORD2 | ||
hkdfInit KEYWORD2 | ||
hkdfProduce KEYWORD2 | ||
chacha20Poly1305Encrypt KEYWORD2 | ||
chacha20Poly1305Decrypt KEYWORD2 | ||
|
||
####################################### | ||
# Constants (LITERAL1) | ||
####################################### | ||
|
||
MD5_NATURAL_LENGTH LITERAL1 | ||
SHA1_NATURAL_LENGTH LITERAL1 | ||
SHA224_NATURAL_LENGTH LITERAL1 | ||
SHA256_NATURAL_LENGTH LITERAL1 | ||
SHA384_NATURAL_LENGTH LITERAL1 | ||
SHA512_NATURAL_LENGTH LITERAL1 | ||
MD5SHA1_NATURAL_LENGTH LITERAL1 | ||
ENCRYPTION_KEY_LENGTH LITERAL1 | ||
CT_MAX_DIFF LITERAL1 |
This file contains hidden or 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,10 @@ | ||
name=CryptoInterface | ||
version=1.0 | ||
author=Anders Löfgren | ||
maintainer=Anders Löfgren | ||
sentence=Interface to the cryptographic library | ||
paragraph=The library acts as a frontend to the cryptographic backend library in ESP8266 Arduino Core. | ||
category=Other | ||
url= | ||
architectures=esp8266 | ||
dot_a_linkage=true |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.