Skip to content

Commit 6c1dabe

Browse files
committed
Add SHA1 and SHA256 API's and examples
1 parent 846ff6c commit 6c1dabe

File tree

9 files changed

+625
-0
lines changed

9 files changed

+625
-0
lines changed

examples/SHA1/SHA1.ino

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
ArduinoBearSSL SHA1
3+
4+
This sketch demonstrates how to create a SHA1 hash and HMAC
5+
for an input string.
6+
7+
This example code is in the public domain.
8+
*/
9+
10+
#include <ArduinoBearSSL.h>
11+
12+
void setup() {
13+
Serial.begin(9600);
14+
while (!Serial);
15+
16+
// expect 0xDA39A3EE5E6B4B0D3255BFEF95601890AFD80709
17+
printSHA1("");
18+
19+
// expect 0x2FD4E1C67A2D28FCED849EE1BB76E7391B93EB12
20+
printSHA1("The quick brown fox jumps over the lazy dog");
21+
22+
// expect 0xFBDB1D1B18AA6C08324B7D64B71FB76370690E1D
23+
printHMACSHA1("", "");
24+
25+
// expect 0xDE7C9B85B8B78AA6BC8A7A36F70A90701C9DB4D9
26+
printHMACSHA1("key", "The quick brown fox jumps over the lazy dog");
27+
}
28+
29+
void loop() {
30+
}
31+
32+
void printSHA1(const char* str) {
33+
Serial.print("SHA1 of '");
34+
Serial.print(str);
35+
Serial.print("' is 0x");
36+
37+
SHA1.beginHash();
38+
SHA1.print(str);
39+
SHA1.endHash();
40+
41+
printResult();
42+
}
43+
44+
void printHMACSHA1(const char* secret, const char* str) {
45+
Serial.print("HMAC-SHA1 of '");
46+
Serial.print(str);
47+
Serial.print("' with secret '");
48+
Serial.print(secret);
49+
Serial.print("' is 0x");
50+
51+
SHA1.beginHmac(secret);
52+
SHA1.print(str);
53+
SHA1.endHmac();
54+
55+
printResult();
56+
}
57+
58+
void printResult()
59+
{
60+
while (SHA1.available()) {
61+
byte b = SHA1.read();
62+
63+
if (b < 16) {
64+
Serial.print("0");
65+
}
66+
67+
Serial.print(b, HEX);
68+
}
69+
Serial.println();
70+
}

examples/SHA256/SHA256.ino

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
ArduinoBearSSL SHA256
3+
4+
This sketch demonstrates how to create a SHA256 hash and HMAC
5+
for an input string.
6+
7+
This example code is in the public domain.
8+
*/
9+
10+
#include <ArduinoBearSSL.h>
11+
12+
void setup() {
13+
Serial.begin(9600);
14+
while (!Serial);
15+
16+
// expect 0xE3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
17+
printSHA256("");
18+
19+
// expect 0xD7A8FBB307D7809469CA9ABCB0082E4F8D5651E46D3CDB762D02D0BF37C9E592
20+
printSHA256("The quick brown fox jumps over the lazy dog");
21+
22+
// expect 0xB613679A0814D9EC772F95D778C35FC5FF1697C493715653C6C712144292C5AD
23+
printHMACSHA256("", "");
24+
25+
// expect 0xF7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8
26+
printHMACSHA256("key", "The quick brown fox jumps over the lazy dog");
27+
}
28+
29+
void loop() {
30+
}
31+
32+
void printSHA256(const char* str) {
33+
Serial.print("SHA256 of '");
34+
Serial.print(str);
35+
Serial.print("' is 0x");
36+
37+
SHA256.beginHash();
38+
SHA256.print(str);
39+
SHA256.endHash();
40+
41+
printResult();
42+
}
43+
44+
void printHMACSHA256(const char* secret, const char* str) {
45+
Serial.print("HMAC-SHA256 of '");
46+
Serial.print(str);
47+
Serial.print("' with secret '");
48+
Serial.print(secret);
49+
Serial.print("' is 0x");
50+
51+
SHA256.beginHmac(secret);
52+
SHA256.print(str);
53+
SHA256.endHmac();
54+
55+
printResult();
56+
}
57+
58+
void printResult()
59+
{
60+
while (SHA256.available()) {
61+
byte b = SHA256.read();
62+
63+
if (b < 16) {
64+
Serial.print("0");
65+
}
66+
67+
Serial.print(b, HEX);
68+
}
69+
Serial.println();
70+
}

src/ArduinoBearSSL.h

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#define _ARDUINO_BEAR_SSL_H_
2727

2828
#include "BearSSLClient.h"
29+
#include "SHA1.h"
30+
#include "SHA256.h"
2931

3032
class ArduinoBearSSLClass {
3133
public:

src/SHA.cpp

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
* Copyright (c) 2019 Arduino SA. All rights reserved.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
#include "SHA.h"
26+
27+
SHAClass::SHAClass(int blockSize, int digestSize) :
28+
_blockSize(blockSize),
29+
_digestSize(digestSize),
30+
_digestIndex(digestSize)
31+
{
32+
_digest = (uint8_t*)malloc(_digestSize);
33+
_secret = (uint8_t*)malloc(_blockSize);
34+
}
35+
36+
SHAClass::~SHAClass()
37+
{
38+
if (_secret) {
39+
free(_secret);
40+
_secret = NULL;
41+
}
42+
43+
if (_digest) {
44+
free(_digest);
45+
_digest = NULL;
46+
}
47+
}
48+
49+
int SHAClass::beginHash()
50+
{
51+
_digestIndex = _digestSize;
52+
53+
return begin();
54+
}
55+
56+
int SHAClass::endHash()
57+
{
58+
if (end(_digest) == 0) {
59+
_digestIndex = _digestSize;
60+
return 0;
61+
} else {
62+
_digestIndex = 0;
63+
return 1;
64+
}
65+
}
66+
67+
int SHAClass::beginHmac(const String& secret)
68+
{
69+
return beginHmac((const uint8_t*)secret.c_str(), secret.length());
70+
}
71+
72+
int SHAClass::beginHmac(const char* secret)
73+
{
74+
return beginHmac((uint8_t*)secret, strlen(secret));
75+
}
76+
77+
int SHAClass::beginHmac(const byte secret[], int length)
78+
{
79+
if (length > _blockSize) {
80+
if (beginHash() == 0) {
81+
return 0;
82+
} else if (write(secret, length) != (size_t)length) {
83+
return 0;
84+
} else if (endHash() == 0) {
85+
return 0;
86+
}
87+
secret = _digest;
88+
_secretLength = _digestSize;;
89+
} else {
90+
_secretLength = length;
91+
}
92+
93+
memset(_secret, 0x00, _blockSize);
94+
memcpy(_secret, secret, _secretLength);
95+
96+
if (beginHash() == 0) {
97+
return 0;
98+
}
99+
100+
uint8_t ipad[_blockSize];
101+
memcpy(ipad, _secret, _blockSize);
102+
103+
for (int i = 0; i < _blockSize; i++) {
104+
ipad[i] ^= 0x36;
105+
}
106+
107+
return (write(ipad, _blockSize) == (size_t)_blockSize);
108+
}
109+
110+
int SHAClass::endHmac()
111+
{
112+
if (endHash() == 0) {
113+
return 0;
114+
}
115+
116+
uint8_t opad[_blockSize];
117+
memcpy(opad, _secret, _blockSize);
118+
119+
for (int i = 0; i < _blockSize; i++) {
120+
opad[i] ^= 0x5c;
121+
}
122+
123+
if (beginHash() == 0) {
124+
return 0;
125+
}
126+
127+
if (write(opad, _blockSize) != (size_t)_blockSize) {
128+
return 0;
129+
}
130+
131+
if (write(_digest, _digestSize) != (size_t)_digestSize) {
132+
return 0;
133+
}
134+
135+
return endHash();
136+
}
137+
138+
int SHAClass::available()
139+
{
140+
return (_digestSize - _digestIndex);
141+
}
142+
143+
int SHAClass::read()
144+
{
145+
if (!available()) {
146+
return -1;
147+
}
148+
149+
return _digest[_digestIndex++];
150+
}
151+
152+
size_t SHAClass::readBytes(char *buffer, size_t length)
153+
{
154+
int toCopy = available();
155+
156+
if (toCopy > (int)length) {
157+
toCopy = length;
158+
}
159+
160+
memcpy(buffer, _digest + _digestIndex, toCopy);
161+
_digestIndex += toCopy;
162+
163+
return toCopy;
164+
}
165+
166+
int SHAClass::peek()
167+
{
168+
if (!available()) {
169+
return -1;
170+
}
171+
172+
return _digest[_digestIndex];
173+
}
174+
175+
void SHAClass::flush()
176+
{
177+
// no-op
178+
}
179+
180+
size_t SHAClass::write(uint8_t data)
181+
{
182+
return write(&data, sizeof(data));
183+
}
184+
185+
size_t SHAClass::write(const uint8_t *buffer, size_t size)
186+
{
187+
if (update(buffer, size) == 0) {
188+
setWriteError();
189+
return 0;
190+
}
191+
192+
return size;
193+
}

0 commit comments

Comments
 (0)