esp8266ndn
NDN Arduino library for ESP8266 and more
Loading...
Searching...
No Matches
interest.hpp
Go to the documentation of this file.
1#ifndef NDNPH_PACKET_INTEREST_HPP
2#define NDNPH_PACKET_INTEREST_HPP
3
4#include "../keychain/private-key.hpp"
5#include "../keychain/public-key.hpp"
6#include "../port/random/port.hpp"
7#include "../port/sha256/port.hpp"
8#include "../port/timingsafe/port.hpp"
9#include "convention.hpp"
10
11namespace ndnph {
12namespace detail {
13
14inline bool
15encodeFwHint(Encoder& encoder, const Name& fwHint) {
16 if (!fwHint) {
17 return false;
18 }
19 return encoder.prependTlv(TT::ForwardingHint, fwHint);
20}
21
22inline bool
23decodeFwHint(const Decoder::Tlv& d, Name* target) {
24 return EvDecoder::decode(d, {TT::ForwardingHint}, EvDecoder::def<TT::Name>(target));
25}
26
35
37class InterestObj : public InRegion {
38public:
41 , canBePrefix(false)
42 , mustBeFresh(false)
43 , nackReason(0) {
44 port::RandomSource::generate(reinterpret_cast<uint8_t*>(&nonce), sizeof(nonce));
45 }
46
47 enum {
50 };
51
52public:
53 InterestParams* params = nullptr; // only relevant on a decoded packet
56 uint32_t nonce = 0;
59 bool canBePrefix : 1;
60 bool mustBeFresh : 1;
61 uint8_t nackReason : 3;
62};
63
64class InterestRefBase : public RefRegion<InterestObj> {
65public:
67
68 const Name& getName() const {
69 return obj->name;
70 }
71
72 bool getCanBePrefix() const {
73 return obj->canBePrefix;
74 }
75
76 bool getMustBeFresh() const {
77 return obj->mustBeFresh;
78 }
79
80 const Name& getFwHint() const {
81 return obj->fwHint;
82 }
83
84 uint32_t getNonce() const {
85 return obj->nonce;
86 }
87
88 uint16_t getLifetime() const {
89 return obj->lifetime;
90 }
91
92 uint8_t getHopLimit() const {
93 return obj->hopLimit;
94 }
95
96protected:
97 ~InterestRefBase() = default;
98
99 void encodeMiddle(Encoder& encoder) const {
100 encoder.prepend(
101 [this](Encoder& encoder) {
102 if (obj->canBePrefix) {
103 encoder.prependTlv(TT::CanBePrefix);
104 }
105 },
106 [this](Encoder& encoder) {
107 if (obj->mustBeFresh) {
109 }
110 },
111 [this](Encoder& encoder) { return encodeFwHint(encoder, obj->fwHint); },
113 [this](Encoder& encoder) {
114 if (obj->lifetime != InterestObj::DefaultLifetime) {
115 encoder.prependTlv(TT::InterestLifetime, tlv::NNI(obj->lifetime));
116 }
117 },
118 [this](Encoder& encoder) {
119 if (obj->hopLimit != InterestObj::MaxHopLimit) {
120 encoder.prependTlv(TT::HopLimit, tlv::NNI1(obj->hopLimit));
121 }
122 });
123 }
124
125 static int findParamsDigest(const Name& name) {
126 int pos = -1;
127 for (const auto& comp : name) {
128 ++pos;
129 if (comp.type() == TT::ParametersSha256DigestComponent) {
130 return pos;
131 }
132 }
133 return -1;
134 }
135};
136
138public:
139 explicit ParameterizedInterestRef() = default;
140
141 explicit ParameterizedInterestRef(InterestObj* interest, tlv::Value appParameters)
142 : InterestRefBase(interest)
143 , m_appParameters(std::move(appParameters)) {}
144
145 void encodeTo(Encoder& encoder) const {
146 if (obj == nullptr) {
147 encoder.setError();
148 return;
149 }
150
151 encodeImpl(encoder, [this](Encoder& encoder) { encodeAppParameters(encoder); });
152 }
153
154protected:
156
157 void encodeName(Encoder& encoder, const tlv::Value& params) const {
158 port::Sha256 hash;
159 hash.update(params.begin(), params.size());
160 uint8_t digestComp[34];
161 if (!hash.final(&digestComp[2])) {
162 encoder.setError();
163 return;
164 }
166 digestComp[1] = NDNPH_SHA256_LEN;
167
168 tlv::Value prefix, suffix;
169 int posParamsDigest = findParamsDigest(obj->name);
170 if (posParamsDigest >= 0) {
171 auto namePrefix = obj->name.slice(0, posParamsDigest);
172 prefix = tlv::Value(namePrefix.value(), namePrefix.length());
173 auto nameSuffix = obj->name.slice(posParamsDigest + 1);
174 suffix = tlv::Value(nameSuffix.value(), nameSuffix.length());
175 } else {
176 prefix = tlv::Value(obj->name.value(), obj->name.length());
177 }
178
179 encoder.prependTlv(TT::Name, prefix, tlv::Value(digestComp, sizeof(digestComp)), suffix);
180 }
181
182 void encodeAppParameters(Encoder& encoder) const {
184 }
185
186 template<typename Fn>
187 void encodeImpl(Encoder& encoder, const Fn& encodeParams) const {
188 tlv::Value params;
189 encoder.prependTlv(
190 TT::Interest, [this, &params](Encoder& encoder) { encodeName(encoder, params); },
191 [this](Encoder& encoder) { encodeMiddle(encoder); },
192 [&](Encoder& encoder) {
193 const uint8_t* afterParams = encoder.begin();
194 encodeParams(encoder);
195 if (!encoder) {
196 return;
197 }
198 params = tlv::Value(encoder.begin(), afterParams);
199 });
200 }
201
202protected:
204};
205
207public:
208 explicit SignedInterestRef() = default;
209
210 explicit SignedInterestRef(InterestObj* interest, tlv::Value appParameters, const PrivateKey& key,
211 ISigInfo sigInfo)
212 : ParameterizedInterestRef(interest, std::move(appParameters))
213 , m_key(&key) {
214 key.updateSigInfo(sigInfo);
215 m_sigInfo = std::move(sigInfo);
216 }
217
218 void encodeTo(Encoder& encoder) const {
219 if (m_key == nullptr) {
220 encoder.setError();
221 return;
222 }
223
224 tlv::Value signedName;
225 int posParamsDigest = findParamsDigest(obj->name);
226 if (posParamsDigest < 0) {
227 signedName = tlv::Value(obj->name.value(), obj->name.length());
228 } else if (static_cast<size_t>(posParamsDigest) == obj->name.size() - 1) {
229 auto prefix = obj->name.getPrefix(-1);
230 signedName = tlv::Value(prefix.value(), prefix.length());
231 } else {
232 encoder.setError();
233 return;
234 }
235
236 const uint8_t* afterSig = encoder.begin();
237 size_t maxSigLen = m_key->getMaxSigLen();
238 uint8_t* sigBuf = encoder.prependRoom(maxSigLen);
239 encoder.prependTypeLength(TT::DSigValue, maxSigLen);
240 const uint8_t* afterSignedPortion = encoder.begin();
241 encoder.prepend([this](Encoder& encoder) { encodeAppParameters(encoder); }, m_sigInfo);
242 if (!encoder) {
243 return;
244 }
245
246 tlv::Value signedPortion(encoder.begin(), afterSignedPortion);
247 ssize_t sigLen = m_key->sign({signedName, signedPortion}, sigBuf);
248 if (sigLen < 0) {
249 encoder.setError();
250 return;
251 }
252
253 encoder.resetFront(const_cast<uint8_t*>(afterSig));
254 encodeImpl(encoder, [=](Encoder& encoder) {
255 encoder.prepend(
256 [=](Encoder& encoder) {
257 uint8_t* room = encoder.prependRoom(signedPortion.size());
258 NDNPH_ASSERT(room != nullptr);
259 if (room != signedPortion.begin()) {
260 std::memmove(room, signedPortion.begin(), signedPortion.size());
261 }
262 },
263 [=](Encoder& encoder) {
264 uint8_t* room = encoder.prependRoom(sigLen);
265 NDNPH_ASSERT(room != nullptr);
266 if (room != sigBuf) {
267 std::memmove(room, sigBuf, sigLen);
268 }
269 encoder.prependTypeLength(TT::ISigValue, sigLen);
270 });
271 });
272 }
273
274private:
275 const PrivateKey* m_key = nullptr;
276 ISigInfo m_sigInfo;
277};
278
279} // namespace detail
280
283 : public Printable
284 , public detail::InterestRefBase {
285public:
286 using InterestRefBase::InterestRefBase;
287
288 void setName(const Name& v) {
289 obj->name = v;
290 }
291
292 void setCanBePrefix(bool v) {
293 obj->canBePrefix = v;
294 }
295
296 void setMustBeFresh(bool v) {
297 obj->mustBeFresh = v;
298 }
299
300 void setFwHint(const Name& v) {
301 obj->fwHint = v;
302 }
303
304 void setNonce(uint32_t v) {
305 obj->nonce = v;
306 }
307
308 void setLifetime(uint16_t v) {
309 obj->lifetime = v;
310 }
311
312 void setHopLimit(uint8_t v) {
313 obj->hopLimit = v;
314 }
315
322 if (obj->params == nullptr) {
323 return tlv::Value();
324 }
325 return obj->params->appParameters;
326 }
327
332 const ISigInfo* getSigInfo() const {
333 return obj->params == nullptr ? nullptr : &obj->params->sigInfo;
334 }
335
337 void encodeTo(Encoder& encoder) const {
338 encoder.prependTlv(TT::Interest, obj->name,
339 [this](Encoder& encoder) { encodeMiddle(encoder); });
340 }
341
344
347 public:
349
350 Signed sign(const PrivateKey& key, ISigInfo sigInfo = ISigInfo()) const {
351 return Signed(obj, m_appParameters, key, std::move(sigInfo));
352 }
353
354 template<typename ISigPolicy>
355 Signed sign(const PrivateKey& key, Region& region, ISigPolicy& policy) const {
356 ISigInfo si;
357 if (!policy.create(region, si)) {
358 return Signed();
359 }
360 return sign(key, si);
361 }
362 };
363
374 Parameterized parameterize(tlv::Value appParameters) const {
375 return Parameterized(obj, std::move(appParameters));
376 }
377
389 template<typename... Arg>
390 Signed sign(Arg&&... arg) const {
391 return parameterize(tlv::Value()).sign(std::forward<Arg>(arg)...);
392 }
393
395 bool decodeFrom(const Decoder::Tlv& input) {
396 return EvDecoder::decode(
397 input, {TT::Interest}, EvDecoder::def<TT::Name>(&obj->name),
398 EvDecoder::def<TT::CanBePrefix>([this](const Decoder::Tlv&) { setCanBePrefix(true); }),
399 EvDecoder::def<TT::MustBeFresh>([this](const Decoder::Tlv&) { setMustBeFresh(true); }),
400 EvDecoder::def<TT::ForwardingHint>(
401 [this](const Decoder::Tlv& d) { return detail::decodeFwHint(d, &obj->fwHint); }),
402 EvDecoder::defNni<TT::Nonce, tlv::NNI4>(&obj->nonce),
403 EvDecoder::defNni<TT::InterestLifetime>(&obj->lifetime),
404 EvDecoder::defNni<TT::HopLimit, tlv::NNI1>(&obj->hopLimit),
405 EvDecoder::def<TT::AppParameters>([this, &input](const Decoder::Tlv& d) {
406 obj->params = regionOf(obj).template make<detail::InterestParams>();
407 if (obj->params == nullptr) {
408 return false;
409 }
410 obj->params->allParams = tlv::Value(d.tlv, input.tlv + input.size);
411 return obj->params->appParameters.decodeFrom(d);
412 }),
413 EvDecoder::def<TT::ISigInfo>([this](const Decoder::Tlv& d) {
414 return obj->params != nullptr && obj->params->sigInfo.decodeFrom(d);
415 }),
416 EvDecoder::def<TT::ISigValue>([this](const Decoder::Tlv& d) {
417 if (obj->params == nullptr) {
418 return false;
419 }
420 obj->params->signedParams = tlv::Value(obj->params->allParams.begin(), d.tlv);
421 return obj->params->sigValue.decodeFrom(d);
422 }));
423 }
424
430 template<typename Encodable>
431 bool decodeFrom(Encodable&& encodable) {
432 if (obj == nullptr) {
433 return false;
434 }
435 Encoder encoder(regionOf(obj));
436 if (!encoder.prepend(std::forward<Encodable>(encodable))) {
437 encoder.discard();
438 return false;
439 }
440 encoder.trim();
441 return Decoder(encoder.begin(), encoder.size()).decode(*this);
442 }
443
451 bool checkDigest() const {
452 if (obj->params == nullptr) {
453 return false;
454 }
455 int posParamsDigest = findParamsDigest(obj->name);
456 if (posParamsDigest < 0) {
457 return false;
458 }
459 Component paramsDigest = obj->name[posParamsDigest];
460
461 uint8_t digest[NDNPH_SHA256_LEN];
462 port::Sha256 hash;
463 hash.update(obj->params->allParams.begin(), obj->params->allParams.size());
464 return hash.final(digest) &&
465 port::TimingSafeEqual()(digest, sizeof(digest), paramsDigest.value(),
466 paramsDigest.length());
467 }
468
476 bool verify(const PublicKey& key) const {
477 if (!checkDigest()) {
478 return false;
479 }
480 int posParamsDigest = findParamsDigest(obj->name);
481 if (static_cast<size_t>(posParamsDigest) != obj->name.size() - 1) {
482 return false;
483 }
484 auto signedName = obj->name.getPrefix(-1);
485 return key.verify(
486 {tlv::Value(signedName.value(), signedName.length()), obj->params->signedParams},
487 obj->params->sigValue.begin(), obj->params->sigValue.size());
488 }
489
490 template<typename DataT>
491 [[deprecated]] bool match(const DataT& data) const {
492 return data.canSatisfy(*this);
493 }
494
495#ifdef NDNPH_PRINT_ARDUINO
496 size_t printTo(::Print& p) const final {
497 size_t count = 0;
498 count += p.print(getName());
499 if (getCanBePrefix()) {
500 count += p.print("[P]");
501 }
502 if (getMustBeFresh()) {
503 count += p.print("[F]");
504 }
505 return count;
506 }
507#endif
508};
509
510#ifdef NDNPH_PRINT_OSTREAM
511inline std::ostream&
512operator<<(std::ostream& os, const Interest& interest) {
513 os << interest.getName();
514 if (interest.getCanBePrefix()) {
515 os << "[P]";
516 }
517 if (interest.getMustBeFresh()) {
518 os << "[F]";
519 }
520 return os;
521}
522#endif
523
524} // namespace ndnph
525
526#endif // NDNPH_PACKET_INTEREST_HPP
static bool generate(uint8_t *output, size_t count)
SHA256 algorithm, implemented with BearSSL.
Definition sha256-bearssl.hpp:11
void update(const uint8_t *chunk, size_t size)
Definition sha256-bearssl.hpp:17
bool final(uint8_t *digest)
Definition sha256-bearssl.hpp:21
Name component.
Definition component.hpp:16
size_t length() const
Definition component.hpp:145
const uint8_t * value() const
Definition component.hpp:149
Decoded TLV.
Definition decoder.hpp:13
const uint8_t * tlv
Definition decoder.hpp:42
TLV decoder.
Definition decoder.hpp:10
bool decode(T &target) const
Decode first TLV into target object.
Definition decoder.hpp:158
TLV encoder that accepts items in reverse order.
Definition encoder.hpp:10
bool prepend(const First &first, const Arg &... arg)
Prepend a sequence of values.
Definition encoder.hpp:123
void trim() const
Release unused space to the Region.
Definition encoder.hpp:58
bool prependTypeLength(uint32_t type, size_t length)
Prepend TLV-TYPE and TLV-LENGTH.
Definition encoder.hpp:103
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
const uint8_t * begin() const
Get output begin.
Definition encoder.hpp:34
bool prependTlv(uint32_t type, OmitEmptyTag omitEmpty, const Arg &... arg)
Prepend TLV, measuring TLV-LENGTH automatically.
Definition encoder.hpp:143
void setError()
Indicate an error has occurred.
Definition encoder.hpp:166
size_t size() const
Get output size.
Definition encoder.hpp:44
void resetFront(uint8_t *pos)
Reset front to given position.
Definition encoder.hpp:81
static bool decode(const Decoder::Tlv &input, std::initializer_list< uint32_t > topTypes, const E &... defs)
Decode input TLV with a sequence of element definitions.
Definition ev-decoder.hpp:115
SignatureInfo on Interest.
Definition sig-info.hpp:51
Base class of an object allocated in a Region.
Definition region.hpp:202
Result of Interest::parameterize operation.
Definition interest.hpp:346
Signed sign(const PrivateKey &key, Region &region, ISigPolicy &policy) const
Definition interest.hpp:355
Signed sign(const PrivateKey &key, ISigInfo sigInfo=ISigInfo()) const
Definition interest.hpp:350
Interest packet.
Definition interest.hpp:284
bool decodeFrom(Encodable &&encodable)
Encode then decode as Interest packet.
Definition interest.hpp:431
void setFwHint(const Name &v)
Definition interest.hpp:300
Parameterized parameterize(tlv::Value appParameters) const
Add AppParameters to the packet.
Definition interest.hpp:374
void encodeTo(Encoder &encoder) const
Encode the Interest without AppParameters.
Definition interest.hpp:337
void setMustBeFresh(bool v)
Definition interest.hpp:296
detail::SignedInterestRef Signed
Result of Interest::sign operation.
Definition interest.hpp:343
void setNonce(uint32_t v)
Definition interest.hpp:304
Signed sign(Arg &&... arg) const
Sign the packet with a private key.
Definition interest.hpp:390
size_t printTo(::Print &p) const final
Definition interest.hpp:496
bool checkDigest() const
Check ParametersSha256DigestComponent.
Definition interest.hpp:451
const ISigInfo * getSigInfo() const
Retrieve SignatureInfo.
Definition interest.hpp:332
void setLifetime(uint16_t v)
Definition interest.hpp:308
bool verify(const PublicKey &key) const
Verify the packet with a public key.
Definition interest.hpp:476
bool match(const DataT &data) const
Definition interest.hpp:491
void setCanBePrefix(bool v)
Definition interest.hpp:292
tlv::Value getAppParameters() const
Retrieve AppParameters.
Definition interest.hpp:321
void setHopLimit(uint8_t v)
Definition interest.hpp:312
void setName(const Name &v)
Definition interest.hpp:288
bool decodeFrom(const Decoder::Tlv &input)
Decode packet.
Definition interest.hpp:395
Name.
Definition name.hpp:14
Definition printing.hpp:22
Private key.
Definition private-key.hpp:9
virtual void updateSigInfo(SigInfo &sigInfo) const =0
Write SigType and KeyLocator.
virtual size_t getMaxSigLen() const =0
virtual ssize_t sign(std::initializer_list< tlv::Value > chunks, uint8_t *sig) const =0
Perform signing.
Public key.
Definition public-key.hpp:9
virtual bool verify(std::initializer_list< tlv::Value > chunks, const uint8_t *sig, size_t sigLen) const =0
Perform verification.
Base class of an object referencing an InRegion object.
Definition region.hpp:210
friend Region & regionOf(const RefRegion< InterestObj > &ref)
Definition region.hpp:228
ObjType * obj
Definition region.hpp:226
RefRegion(ObjType *obj=nullptr)
Definition region.hpp:215
Region-based memory allocator thats owns memory of NDNph objects.
Definition region.hpp:9
Region & region
Definition region.hpp:194
Fields in Interest or Nack.
Definition interest.hpp:37
bool canBePrefix
Definition interest.hpp:59
Name fwHint
Definition interest.hpp:55
uint16_t lifetime
Definition interest.hpp:57
uint8_t hopLimit
Definition interest.hpp:58
uint8_t nackReason
Definition interest.hpp:61
bool mustBeFresh
Definition interest.hpp:60
InterestObj(Region &region)
Definition interest.hpp:39
InterestParams * params
Definition interest.hpp:53
uint32_t nonce
Definition interest.hpp:56
@ MaxHopLimit
Definition interest.hpp:49
@ DefaultLifetime
Definition interest.hpp:48
Name name
Definition interest.hpp:54
Definition interest.hpp:64
uint32_t getNonce() const
Definition interest.hpp:84
bool getCanBePrefix() const
Definition interest.hpp:72
void encodeMiddle(Encoder &encoder) const
Definition interest.hpp:99
uint8_t getHopLimit() const
Definition interest.hpp:92
const Name & getFwHint() const
Definition interest.hpp:80
uint16_t getLifetime() const
Definition interest.hpp:88
bool getMustBeFresh() const
Definition interest.hpp:76
const Name & getName() const
Definition interest.hpp:68
static int findParamsDigest(const Name &name)
Definition interest.hpp:125
Definition interest.hpp:137
void encodeTo(Encoder &encoder) const
Definition interest.hpp:145
tlv::Value m_appParameters
Definition interest.hpp:203
ParameterizedInterestRef(InterestObj *interest, tlv::Value appParameters)
Definition interest.hpp:141
void encodeImpl(Encoder &encoder, const Fn &encodeParams) const
Definition interest.hpp:187
void encodeAppParameters(Encoder &encoder) const
Definition interest.hpp:182
void encodeName(Encoder &encoder, const tlv::Value &params) const
Definition interest.hpp:157
Definition interest.hpp:206
void encodeTo(Encoder &encoder) const
Definition interest.hpp:218
SignedInterestRef(InterestObj *interest, tlv::Value appParameters, const PrivateKey &key, ISigInfo sigInfo)
Definition interest.hpp:210
NonNegativeInteger encoding.
Definition nni.hpp:118
Encode to a TLV element where TLV-VALUE is a NonNegativeInteger.
Definition nni.hpp:170
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
Definition nni.hpp:12
#define NDNPH_ASSERT(x)
Definition common.hpp:30
#define NDNPH_SHA256_LEN
SHA256 digest length.
Definition common.hpp:34
@ Interest
Definition an.hpp:30
@ ParametersSha256DigestComponent
Definition an.hpp:22
@ MustBeFresh
Definition an.hpp:32
@ InterestLifetime
Definition an.hpp:35
@ ForwardingHint
Definition an.hpp:33
@ Nonce
Definition an.hpp:34
@ Name
Definition an.hpp:19
@ ISigValue
Definition an.hpp:39
@ DSigValue
Definition an.hpp:48
@ AppParameters
Definition an.hpp:37
@ HopLimit
Definition an.hpp:36
bool decodeFwHint(const Decoder::Tlv &d, Name *target)
Definition interest.hpp:23
bool encodeFwHint(Encoder &encoder, const Name &fwHint)
Definition interest.hpp:15
Definition fs.hpp:33
Fields in parameterized/signed Interest.
Definition interest.hpp:28
tlv::Value sigValue
Definition interest.hpp:31
tlv::Value appParameters
Definition interest.hpp:29
tlv::Value signedParams
Definition interest.hpp:32
ISigInfo sigInfo
Definition interest.hpp:30
tlv::Value allParams
Definition interest.hpp:33