esp8266ndn
NDN Arduino library for ESP8266 and more
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
data.hpp
Go to the documentation of this file.
1#ifndef NDNPH_PACKET_DATA_HPP
2#define NDNPH_PACKET_DATA_HPP
3
4#include "../keychain/private-key.hpp"
5#include "../keychain/public-key.hpp"
6#include "../port/sha256/port.hpp"
7#include "../port/timingsafe/port.hpp"
8#include "convention.hpp"
9#include "sig-info.hpp"
10
11namespace ndnph {
12namespace detail {
13
21
41
42class SignedDataRef : public RefRegion<DataObj> {
43public:
44 explicit SignedDataRef() = default;
45
46 explicit SignedDataRef(DataObj* data, const PrivateKey& key, DSigInfo sigInfo)
47 : RefRegion(data)
48 , m_key(&key) {
49 key.updateSigInfo(sigInfo);
50 m_sigInfo = std::move(sigInfo);
51 }
52
53 void encodeTo(Encoder& encoder) const {
54 if (m_key == nullptr) {
55 encoder.setError();
56 return;
57 }
58
59 const uint8_t* afterSig = encoder.begin();
60 size_t maxSigLen = m_key->getMaxSigLen();
61 uint8_t* sigBuf = encoder.prependRoom(maxSigLen);
62 encoder.prependTypeLength(TT::DSigValue, maxSigLen);
63 const uint8_t* afterSignedPortion = encoder.begin();
64 encodeSignedPortion(encoder);
65 if (!encoder) {
66 return;
67 }
68
69 tlv::Value signedPortion(encoder.begin(), afterSignedPortion);
70 ssize_t sigLen = m_key->sign({signedPortion}, sigBuf);
71 if (sigLen < 0) {
72 encoder.setError();
73 return;
74 }
75
76 encoder.resetFront(const_cast<uint8_t*>(afterSig));
77 encoder.prependTlv(
79 [=](Encoder& encoder) {
80 uint8_t* room = encoder.prependRoom(signedPortion.size());
81 NDNPH_ASSERT(room != nullptr);
82 if (room != signedPortion.begin()) {
83 std::memmove(room, signedPortion.begin(), signedPortion.size());
84 }
85 },
86 [=](Encoder& encoder) {
87 uint8_t* room = encoder.prependRoom(sigLen);
88 NDNPH_ASSERT(room != nullptr);
89 if (room != sigBuf) {
90 std::memmove(room, sigBuf, sigLen);
91 }
92 encoder.prependTypeLength(TT::DSigValue, sigLen);
93 });
94 }
95
96private:
97 void encodeSignedPortion(Encoder& encoder) const {
98 encoder.prepend(
99 obj->name,
100 [this](Encoder& encoder) {
101 encoder.prependTlv(
102 TT::MetaInfo, Encoder::OmitEmpty,
103 [this](Encoder& encoder) {
104 if (obj->contentType != DataObj::DefaultContentType) {
105 encoder.prependTlv(TT::ContentType, tlv::NNI(obj->contentType));
106 }
107 },
108 [this](Encoder& encoder) {
109 if (obj->freshnessPeriod != DataObj::DefaultFreshnessPeriod) {
110 encoder.prependTlv(TT::FreshnessPeriod, tlv::NNI(obj->freshnessPeriod));
111 }
112 },
113 [this](Encoder& encoder) {
114 if (obj->isFinalBlock) {
115 auto comp = obj->name[-1];
116 encoder.prependTlv(TT::FinalBlock, tlv::Value(comp.tlv(), comp.size()));
117 }
118 });
119 },
120 [this](Encoder& encoder) {
121 encoder.prependTlv(TT::Content, Encoder::OmitEmpty, obj->content);
122 },
123 m_sigInfo);
124 }
125
126private:
127 const PrivateKey* m_key = nullptr;
128 DSigInfo m_sigInfo;
129};
130
131} // namespace detail
132
134class Data
135 : public Printable
136 , public RefRegion<detail::DataObj> {
137public:
138 using RefRegion::RefRegion;
139
140 const Name& getName() const {
141 return obj->name;
142 }
143
144 void setName(const Name& v) {
145 obj->name = v;
146 }
147
148 uint8_t getContentType() const {
149 return obj->contentType;
150 }
151
152 void setContentType(uint8_t v) {
153 obj->contentType = v;
154 }
155
156 uint32_t getFreshnessPeriod() const {
157 return obj->freshnessPeriod;
158 }
159
160 void setFreshnessPeriod(uint32_t v) {
161 obj->freshnessPeriod = v;
162 }
163
164 bool getIsFinalBlock() const {
165 return obj->isFinalBlock;
166 }
167
168 void setIsFinalBlock(bool v) {
169 obj->isFinalBlock = v;
170 }
171
173 return obj->content;
174 }
175
177 obj->content = std::move(v);
178 }
179
184 const DSigInfo* getSigInfo() const {
185 return obj->sig == nullptr ? nullptr : &obj->sig->sigInfo;
186 }
187
192 void encodeTo(Encoder& encoder) const {
193 if (obj->sig == nullptr) {
194 encoder.setError();
195 return;
196 }
197 obj->sig->wholePacket.encodeTo(encoder);
198 }
199
201 bool decodeFrom(const Decoder::Tlv& input) {
202 obj->sig = regionOf(obj).template make<detail::DataSigned>();
203 if (obj->sig == nullptr) {
204 return false;
205 }
206 obj->sig->wholePacket = tlv::Value(input.tlv, input.size);
207 return EvDecoder::decode(
208 input, {TT::Data}, EvDecoder::def<TT::Name>(&obj->name),
209 EvDecoder::def<TT::MetaInfo>([this](const Decoder::Tlv& d) {
210 return EvDecoder::decode(d, {}, EvDecoder::defNni<TT::ContentType>(&obj->contentType),
211 EvDecoder::defNni<TT::FreshnessPeriod>(&obj->freshnessPeriod),
212 EvDecoder::def<TT::FinalBlock>([this](const Decoder::Tlv& d) {
213 auto comp = getName()[-1];
214 setIsFinalBlock(
215 d.length == comp.size() &&
216 std::equal(d.value, d.value + d.length, comp.tlv()));
217 }));
218 }),
219 EvDecoder::def<TT::Content>(&obj->content), EvDecoder::def<TT::DSigInfo>(&obj->sig->sigInfo),
220 EvDecoder::def<TT::DSigValue>([this, &input](const Decoder::Tlv& d) {
221 obj->sig->signedPortion = tlv::Value(input.value, d.tlv);
222 return obj->sig->sigValue.decodeFrom(d);
223 }));
224 }
225
231 template<typename Encodable>
232 bool decodeFrom(Encodable&& encodable) {
233 if (obj == nullptr) {
234 return false;
235 }
236 Encoder encoder(regionOf(obj));
237 if (!encoder.prepend(std::forward<Encodable>(encodable))) {
238 encoder.discard();
239 return false;
240 }
241 encoder.trim();
242 return Decoder(encoder.begin(), encoder.size()).decode(*this);
243 }
244
247
254 Signed sign(const PrivateKey& key, DSigInfo sigInfo = DSigInfo()) const {
255 return Signed(obj, key, std::move(sigInfo));
256 }
257
263 bool verify(const PublicKey& key) const {
264 return obj->sig != nullptr && key.verify({obj->sig->signedPortion}, obj->sig->sigValue.begin(),
265 obj->sig->sigValue.size());
266 }
267
273 bool computeImplicitDigest(uint8_t digest[NDNPH_SHA256_LEN]) const {
274 if (obj->sig == nullptr) {
275 return false;
276 }
277 port::Sha256 hash;
278 hash.update(obj->sig->wholePacket.begin(), obj->sig->wholePacket.size());
279 return hash.final(digest);
280 }
281
287 Name getFullName(Region& region) const {
288 uint8_t digest[NDNPH_SHA256_LEN];
289 if (!computeImplicitDigest(digest)) {
290 return Name();
291 }
292 return getName().append(region, convention::ImplicitDigest(), digest);
293 }
294
296 CanSatisfyNone = 0,
297 CanSatisfyInCache = 1 << 0,
298 };
299
308 template<typename InterestT>
309 bool canSatisfy(const InterestT& interest, CanSatisfyOptions opts = CanSatisfyNone) const {
310 if ((opts & CanSatisfyInCache) != 0 && interest.getMustBeFresh() && getFreshnessPeriod() == 0) {
311 return false;
312 }
313 const Name& interestName = interest.getName();
314 const Name& dataName = getName();
315 switch (interestName.compare(dataName)) {
316 case Name::CMP_EQUAL:
317 return true;
318 case Name::CMP_LPREFIX:
319 return interest.getCanBePrefix();
320 case Name::CMP_RPREFIX: {
321 Component lastComp = interestName[-1];
322 uint8_t digest[NDNPH_SHA256_LEN];
323 return interestName.size() == dataName.size() + 1 &&
324 lastComp.is<convention::ImplicitDigest>() && computeImplicitDigest(digest) &&
325 port::TimingSafeEqual()(digest, sizeof(digest), lastComp.value(), lastComp.length());
326 }
327 default:
328 return false;
329 }
330 }
331
332#ifdef NDNPH_PRINT_ARDUINO
333 size_t printTo(::Print& p) const final {
334 return p.print(getName());
335 }
336#endif
337};
338
339#ifdef NDNPH_PRINT_OSTREAM
340inline std::ostream&
341operator<<(std::ostream& os, const Data& data) {
342 return os << data.getName();
343}
344#endif
345
346} // namespace ndnph
347
348#endif // NDNPH_PACKET_DATA_HPP
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
bool is() const
Definition component.hpp:189
SignatureInfo on Data.
Definition sig-info.hpp:59
Data packet.
Definition data.hpp:136
const DSigInfo * getSigInfo() const
Retrieve SignatureInfo.
Definition data.hpp:184
bool canSatisfy(const InterestT &interest, CanSatisfyOptions opts=CanSatisfyNone) const
Determine whether Data can satisfy Interest.
Definition data.hpp:309
bool getIsFinalBlock() const
Definition data.hpp:164
void setContentType(uint8_t v)
Definition data.hpp:152
uint32_t getFreshnessPeriod() const
Definition data.hpp:156
void setContent(tlv::Value v)
Definition data.hpp:176
void setName(const Name &v)
Definition data.hpp:144
tlv::Value getContent() const
Definition data.hpp:172
bool decodeFrom(Encodable &&encodable)
Encode then decode as Data packet.
Definition data.hpp:232
const Name & getName() const
Definition data.hpp:140
Signed sign(const PrivateKey &key, DSigInfo sigInfo=DSigInfo()) const
Sign the packet with a private key.
Definition data.hpp:254
uint8_t getContentType() const
Definition data.hpp:148
void setFreshnessPeriod(uint32_t v)
Definition data.hpp:160
void setIsFinalBlock(bool v)
Definition data.hpp:168
size_t printTo(::Print &p) const final
Definition data.hpp:333
bool computeImplicitDigest(uint8_t digest[NDNPH_SHA256_LEN]) const
Compute implicit digest.
Definition data.hpp:273
bool verify(const PublicKey &key) const
Verify the packet with a public key.
Definition data.hpp:263
bool decodeFrom(const Decoder::Tlv &input)
Decode packet.
Definition data.hpp:201
Name getFullName(Region &region) const
Obtain full name with implicit digest.
Definition data.hpp:287
void encodeTo(Encoder &encoder) const
Prepend the original packet to Encoder.
Definition data.hpp:192
CanSatisfyOptions
Definition data.hpp:295
Decoded TLV.
Definition decoder.hpp:13
const uint8_t * tlv
Definition decoder.hpp:42
size_t length
Definition decoder.hpp:39
const uint8_t * value
Definition decoder.hpp:40
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
@ OmitEmpty
Definition encoder.hpp:131
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
Base class of an object allocated in a Region.
Definition region.hpp:202
Name.
Definition name.hpp:14
size_t size() const
Get number of components.
Definition name.hpp:86
CompareResult compare(const Name &other) const
Compare with other name.
Definition name.hpp:217
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
ObjType * obj
Definition region.hpp:226
Region-based memory allocator thats owns memory of NDNph objects.
Definition region.hpp:9
Region & region
Definition region.hpp:194
Definition convention.hpp:74
Fields in Data.
Definition data.hpp:23
bool isFinalBlock
Definition data.hpp:39
uint8_t contentType
Definition data.hpp:38
@ DefaultFreshnessPeriod
Definition data.hpp:30
@ DefaultContentType
Definition data.hpp:29
DataObj(Region &region)
Definition data.hpp:25
tlv::Value content
Definition data.hpp:36
uint32_t freshnessPeriod
Definition data.hpp:37
DataSigned * sig
Definition data.hpp:34
Name name
Definition data.hpp:35
Definition data.hpp:42
void encodeTo(Encoder &encoder) const
Definition data.hpp:53
SignedDataRef(DataObj *data, const PrivateKey &key, DSigInfo sigInfo)
Definition data.hpp:46
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
@ Blob
Definition an.hpp:66
@ FinalBlock
Definition an.hpp:45
@ DSigInfo
Definition an.hpp:47
@ DSigValue
Definition an.hpp:48
@ Content
Definition an.hpp:46
@ Data
Definition an.hpp:41
Definition fs.hpp:33
Fields in Data signature.
Definition data.hpp:15
tlv::Value signedPortion
Definition data.hpp:18
tlv::Value sigValue
Definition data.hpp:17
tlv::Value wholePacket
Definition data.hpp:19
DSigInfo sigInfo
Definition data.hpp:16