esp8266ndn
NDN Arduino library for ESP8266 and more
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mbed-common.hpp
Go to the documentation of this file.
1#ifndef NDNPH_PORT_MBED_COMMON_HPP
2#define NDNPH_PORT_MBED_COMMON_HPP
3#ifdef NDNPH_HAVE_MBED
4
5#include "../keychain/iv.hpp"
6#include "random/port.hpp"
7#include <mbedtls/bignum.h>
8#include <mbedtls/ecdh.h>
9#include <mbedtls/ecp.h>
10#include <mbedtls/gcm.h>
11#include <mbedtls/md.h>
12#include <mbedtls/sha256.h>
13
14#ifndef MBEDTLS_ECDSA_DETERMINISTIC
15#error MBEDTLS_ECDSA_DETERMINISTIC must be declared
16#endif
17
18#if MBEDTLS_VERSION_MAJOR >= 3
19#define NDNPH_MBEDTLS_RET2(func) func
20#else
21#define NDNPH_MBEDTLS_RET2(func) func##_ret
22#endif
23
24namespace ndnph {
26namespace mbedtls {
27
29inline int
30rng(void*, uint8_t* output, size_t count) {
31 bool ok = port::RandomSource::generate(output, count);
32 return ok ? 0 : -1;
33}
34
36class Sha256 {
37public:
38 explicit Sha256() {
39 mbedtls_sha256_init(&m_ctx);
40 m_ok = NDNPH_MBEDTLS_RET2(mbedtls_sha256_starts)(&m_ctx, 0) == 0;
41 }
42
44 mbedtls_sha256_free(&m_ctx);
45 }
46
47 void update(const uint8_t* chunk, size_t size) {
48 m_ok = m_ok && NDNPH_MBEDTLS_RET2(mbedtls_sha256_update)(&m_ctx, chunk, size) == 0;
49 }
50
51 bool final(uint8_t digest[NDNPH_SHA256_LEN]) {
52 m_ok = m_ok && NDNPH_MBEDTLS_RET2(mbedtls_sha256_finish)(&m_ctx, digest) == 0;
53 return m_ok;
54 }
55
56private:
57 mbedtls_sha256_context m_ctx;
58 bool m_ok = false;
59};
60
66template<mbedtls_md_type_t mdType, size_t mdSize>
67class Hmac {
68public:
70 explicit Hmac(const uint8_t* key, size_t keyLen) {
71 mbedtls_md_init(&m_ctx);
72 m_ok = mbedtls_md_setup(&m_ctx, mbedtls_md_info_from_type(mdType), 1) == 0 &&
73 mbedtls_md_hmac_starts(&m_ctx, key, keyLen) == 0;
74 }
75
77 mbedtls_md_free(&m_ctx);
78 }
79
81 void update(const uint8_t* chunk, size_t size) {
82 m_ok = m_ok && mbedtls_md_hmac_update(&m_ctx, chunk, size) == 0;
83 }
84
90 bool final(uint8_t result[mdSize]) {
91 m_ok =
92 m_ok && mbedtls_md_hmac_finish(&m_ctx, result) == 0 && mbedtls_md_hmac_reset(&m_ctx) == 0;
93 return m_ok;
94 }
95
96private:
97 mbedtls_md_context_t m_ctx;
98 bool m_ok = false;
99};
100
102class Mpi {
103public:
105 explicit Mpi() {
106 mbedtls_mpi_init(&m_value);
107 }
108
110 explicit Mpi(const mbedtls_mpi* src)
111 : Mpi() {
112 mbedtls_mpi_copy(&m_value, src);
113 }
114
116 explicit Mpi(mbedtls_mpi_sint src)
117 : Mpi() {
118 mbedtls_mpi_lset(&m_value, src);
119 }
120
122 mbedtls_mpi_free(&m_value);
123 }
124
125 operator mbedtls_mpi*() {
126 return &m_value;
127 }
128
129 operator const mbedtls_mpi*() const {
130 return &m_value;
131 }
132
134 Mpi& operator=(const Mpi&) = delete;
135
141 mbedtls_mpi_swap(&m_value, &y.m_value);
142 return *this;
143 }
144
145private:
146 mbedtls_mpi m_value;
147};
148
150class EcPoint {
151public:
153 explicit EcPoint() {
154 mbedtls_ecp_point_init(&m_value);
155 }
156
158 explicit EcPoint(const mbedtls_ecp_point* q)
159 : EcPoint() {
160 if (q != nullptr) {
161 mbedtls_ecp_copy(&m_value, q);
162 }
163 }
164
166 mbedtls_ecp_point_free(&m_value);
167 }
168
169 operator mbedtls_ecp_point*() {
170 return &m_value;
171 }
172
173 operator const mbedtls_ecp_point*() const {
174 return &m_value;
175 }
176
178 EcPoint& operator=(const EcPoint&) = delete;
179
180 bool writeBinary(mbedtls_ecp_group* group, uint8_t* room, size_t length) const {
181 size_t actualLength = 0;
182 return mbedtls_ecp_point_write_binary(group, *this, MBEDTLS_ECP_PF_UNCOMPRESSED, &actualLength,
183 room, length) == 0 &&
184 actualLength == length;
185 }
186
187 void encodeTo(mbedtls_ecp_group* group, Encoder& encoder, size_t length) const {
188 uint8_t* room = encoder.prependRoom(length);
189 if (room == nullptr) {
190 return;
191 }
192
193 if (!writeBinary(group, room, length)) {
194 encoder.setError();
195 }
196 }
197
198 bool readBinary(mbedtls_ecp_group* group, const uint8_t* value, size_t length) {
199 return mbedtls_ecp_point_read_binary(group, *this, value, length) == 0 &&
200 mbedtls_ecp_check_pubkey(group, *this) == 0;
201 }
202
203 bool decodeFrom(mbedtls_ecp_group* group, const Decoder::Tlv& d) {
204 return readBinary(group, d.value, d.length);
205 }
206
207private:
208 mbedtls_ecp_point m_value;
209};
210
212template<typename Curve>
213class EcCurvePoint : public EcPoint {
214public:
215 bool writeBinary(uint8_t room[Curve::PubLen::value]) const {
216 return EcPoint::writeBinary(Curve::group(), room, Curve::PubLen::value);
217 }
218
219 void encodeTo(Encoder& encoder) const {
220 return EcPoint::encodeTo(Curve::group(), encoder, Curve::PubLen::value);
221 }
222
223 bool readBinary(const uint8_t* value, size_t length) {
224 return EcPoint::readBinary(Curve::group(), value, length);
225 }
226
227 bool decodeFrom(const Decoder::Tlv& d) {
228 return EcPoint::decodeFrom(Curve::group(), d);
229 }
230};
231
233class P256 {
234public:
235 using PvtLen = std::integral_constant<size_t, 32>;
236 using PubLen = std::integral_constant<size_t, 65>;
237 using MaxSigLen = std::integral_constant<size_t, 74>;
239
240 static mbedtls_ecp_group* group() {
241 static struct S {
242 S() {
243 int res = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
244 NDNPH_ASSERT(res == 0);
245 }
246 mbedtls_ecp_group grp;
247 } s;
248 return &s.grp;
249 };
250
252 using SharedSecret = std::array<uint8_t, PvtLen::value>;
253
255 static bool ecdh(const mbedtls_mpi* pvt, const mbedtls_ecp_point* pub, SharedSecret& shared) {
256 Mpi z;
257 return mbedtls_ecdh_compute_shared(group(), z, pub, pvt, rng, nullptr) == 0 &&
258 mbedtls_mpi_write_binary(z, shared.data(), shared.size()) == 0;
259 }
260};
261
269template<int keyBits>
270class AesGcm {
271public:
272 static_assert(keyBits == 128 || keyBits == 256, "");
273 using Key = std::array<uint8_t, keyBits / 8>;
275 using TagLen = std::integral_constant<size_t, 16>;
276
277 explicit AesGcm() {
278 mbedtls_gcm_init(&m_ctx);
279 }
280
282 mbedtls_gcm_free(&m_ctx);
283 }
284
285 AesGcm(const AesGcm&) = delete;
286 AesGcm& operator=(const AesGcm&) = delete;
287
292 bool import(const Key& key) {
293 m_ok = mbedtls_gcm_setkey(&m_ctx, MBEDTLS_CIPHER_ID_AES, key.data(), keyBits) == 0 &&
294 m_ivEncrypt.randomize();
295 return m_ok;
296 }
297
308 template<typename Encrypted>
309 tlv::Value encrypt(Region& region, tlv::Value plaintext, const uint8_t* aad = nullptr,
310 size_t aadLen = 0) {
311 checkEncryptedMessage<Encrypted>();
312 Encoder encoder(region);
313 auto place = Encrypted::prependInPlace(encoder, plaintext.size());
314 encoder.trim();
315
316 bool ok = m_ok && !!encoder && m_ivEncrypt.write(place.iv) &&
317 mbedtls_gcm_crypt_and_tag(&m_ctx, MBEDTLS_GCM_ENCRYPT, plaintext.size(), place.iv,
318 IvLen::value, aad, aadLen, plaintext.begin(),
319 place.ciphertext, TagLen::value, place.tag) == 0 &&
320 m_ivEncrypt.advance(plaintext.size());
321 if (!ok) {
322 encoder.discard();
323 return tlv::Value();
324 }
325 return tlv::Value(encoder);
326 }
327
343 template<typename Encrypted>
344 tlv::Value decrypt(Region& region, const Encrypted& encrypted, const uint8_t* aad = nullptr,
345 size_t aadLen = 0) {
346 checkEncryptedMessage<Encrypted>();
347 uint8_t* plaintext = region.alloc(encrypted.ciphertext.size());
348 bool ok =
349 m_ok && m_ivDecrypt.check(encrypted.iv.data(), encrypted.ciphertext.size()) &&
350 plaintext != nullptr &&
351 mbedtls_gcm_auth_decrypt(&m_ctx, encrypted.ciphertext.size(), encrypted.iv.data(),
352 encrypted.iv.size(), aad, aadLen, encrypted.tag.data(),
353 encrypted.tag.size(), encrypted.ciphertext.begin(), plaintext) == 0;
354 if (!ok) {
355 region.free(plaintext, encrypted.ciphertext.size());
356 return tlv::Value();
357 }
358 return tlv::Value(plaintext, encrypted.ciphertext.size());
359 }
360
362 m_ivDecrypt = AesGcmIvHelper();
363 }
364
365private:
366 template<typename Encrypted>
367 static void checkEncryptedMessage() {
368 static_assert(Encrypted::IvLen::value == IvLen::value, "");
369 static_assert(Encrypted::TagLen::value == TagLen::value, "");
370 }
371
372private:
373 mbedtls_gcm_context m_ctx;
374 AesGcmIvHelper m_ivEncrypt;
375 AesGcmIvHelper m_ivDecrypt;
376 bool m_ok = false;
377};
378
379} // namespace mbedtls
380} // namespace ndnph
381
382#endif // NDNPH_HAVE_MBED
383#endif // NDNPH_PORT_MBED_COMMON_HPP
static bool generate(uint8_t *output, size_t count)
AES-GCM Initialization Vector generator and checker.
Definition iv.hpp:18
bool check(const uint8_t *iv, size_t size)
Check received IV.
Definition iv.hpp:59
std::integral_constant< size_t, 12 > IvLen
IV length.
Definition iv.hpp:21
bool write(uint8_t room[12])
Write IV to room .
Definition iv.hpp:33
bool randomize()
Randomize the random number portion.
Definition iv.hpp:27
bool advance(size_t size)
Advance the counter portion.
Definition iv.hpp:43
Decoded TLV.
Definition decoder.hpp:13
size_t length
Definition decoder.hpp:39
const uint8_t * value
Definition decoder.hpp:40
TLV encoder that accepts items in reverse order.
Definition encoder.hpp:10
void trim() const
Release unused space to the Region.
Definition encoder.hpp:58
uint8_t * prependRoom(size_t size)
Make room to prepend an object.
Definition encoder.hpp:90
void discard()
Release all space to the Region.
Definition encoder.hpp:72
void setError()
Indicate an error has occurred.
Definition encoder.hpp:166
Region-based memory allocator thats owns memory of NDNph objects.
Definition region.hpp:9
uint8_t * alloc(size_t size)
Allocate a buffer with no alignment requirement.
Definition region.hpp:27
bool free(const uint8_t *first, const uint8_t *last)
Deallocate (part of) last allocated buffer.
Definition region.hpp:51
AES-GCM secret key.
Definition mbed-common.hpp:270
tlv::Value encrypt(Region &region, tlv::Value plaintext, const uint8_t *aad=nullptr, size_t aadLen=0)
Encrypt to encrypted-message.
Definition mbed-common.hpp:309
AesGcm()
Definition mbed-common.hpp:277
~AesGcm()
Definition mbed-common.hpp:281
tlv::Value decrypt(Region &region, const Encrypted &encrypted, const uint8_t *aad=nullptr, size_t aadLen=0)
Decrypt from encrypted-message.
Definition mbed-common.hpp:344
AesGcm(const AesGcm &)=delete
AesGcm & operator=(const AesGcm &)=delete
std::integral_constant< size_t, 16 > TagLen
Definition mbed-common.hpp:275
std::array< uint8_t, keyBits/8 > Key
Definition mbed-common.hpp:273
void clearDecryptIvChecker()
Definition mbed-common.hpp:361
AesGcmIvHelper::IvLen IvLen
Definition mbed-common.hpp:274
EC point associated with a curve.
Definition mbed-common.hpp:213
bool readBinary(const uint8_t *value, size_t length)
Definition mbed-common.hpp:223
bool decodeFrom(const Decoder::Tlv &d)
Definition mbed-common.hpp:227
void encodeTo(Encoder &encoder) const
Definition mbed-common.hpp:219
bool writeBinary(uint8_t room[Curve::PubLen::value]) const
Definition mbed-common.hpp:215
EC point.
Definition mbed-common.hpp:150
~EcPoint()
Definition mbed-common.hpp:165
EcPoint(const mbedtls_ecp_point *q)
Construct from EC point.
Definition mbed-common.hpp:158
void encodeTo(mbedtls_ecp_group *group, Encoder &encoder, size_t length) const
Definition mbed-common.hpp:187
EcPoint & operator=(const EcPoint &)=delete
Copy assignment is disallowed due to lack of error handling.
bool decodeFrom(mbedtls_ecp_group *group, const Decoder::Tlv &d)
Definition mbed-common.hpp:203
bool readBinary(mbedtls_ecp_group *group, const uint8_t *value, size_t length)
Definition mbed-common.hpp:198
EcPoint()
Construct zero.
Definition mbed-common.hpp:153
bool writeBinary(mbedtls_ecp_group *group, uint8_t *room, size_t length) const
Definition mbed-common.hpp:180
HMAC algorithm.
Definition mbed-common.hpp:67
~Hmac()
Definition mbed-common.hpp:76
void update(const uint8_t *chunk, size_t size)
Append bytes into hash state.
Definition mbed-common.hpp:81
Hmac(const uint8_t *key, size_t keyLen)
Start HMAC operation and set key.
Definition mbed-common.hpp:70
Multi-Precision Integer.
Definition mbed-common.hpp:102
Mpi & operator=(const Mpi &)=delete
Copy assignment is disallowed due to lack of error handling.
Mpi()
Construct zero.
Definition mbed-common.hpp:105
Mpi(const mbedtls_mpi *src)
Construct from MPI.
Definition mbed-common.hpp:110
Mpi(mbedtls_mpi_sint src)
Construct from integer.
Definition mbed-common.hpp:116
Mpi & operator=(Mpi &&y)
Move assignment.
Definition mbed-common.hpp:140
~Mpi()
Definition mbed-common.hpp:121
EC curve P256.
Definition mbed-common.hpp:233
std::integral_constant< size_t, 74 > MaxSigLen
Definition mbed-common.hpp:237
std::array< uint8_t, PvtLen::value > SharedSecret
ECDH shared secret buffer.
Definition mbed-common.hpp:252
static bool ecdh(const mbedtls_mpi *pvt, const mbedtls_ecp_point *pub, SharedSecret &shared)
Compute ECDH shared secret.
Definition mbed-common.hpp:255
std::integral_constant< size_t, 65 > PubLen
Definition mbed-common.hpp:236
static mbedtls_ecp_group * group()
Definition mbed-common.hpp:240
std::integral_constant< size_t, 32 > PvtLen
Definition mbed-common.hpp:235
SHA256 hash function.
Definition mbed-common.hpp:36
Sha256()
Definition mbed-common.hpp:38
~Sha256()
Definition mbed-common.hpp:43
void update(const uint8_t *chunk, size_t size)
Definition mbed-common.hpp:47
A sequence of bytes, usually TLV-VALUE.
Definition value.hpp:11
const uint8_t * begin() const
Definition value.hpp:38
size_t size() const
Definition value.hpp:46
#define NDNPH_ASSERT(x)
Definition common.hpp:30
#define NDNPH_SHA256_LEN
SHA256 digest length.
Definition common.hpp:34
#define NDNPH_MBEDTLS_RET2(func)
Definition mbed-common.hpp:21
int rng(void *, uint8_t *output, size_t count)
Random number generator for various Mbed TLS library functions.
Definition mbed-common.hpp:30
Definition fs.hpp:33