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 
11 namespace ndnph {
12 namespace detail {
13 
15 struct DataSigned {
20 };
21 
23 class DataObj : public InRegion {
24 public:
25  explicit DataObj(Region& region)
26  : InRegion(region) {}
27 
28  enum {
31  };
32 
33 public:
34  DataSigned* sig = nullptr;
39  bool isFinalBlock = false;
40 };
41 
42 class SignedDataRef : public RefRegion<DataObj> {
43 public:
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(
78  TT::Data,
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 
96 private:
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 
126 private:
127  const PrivateKey* m_key = nullptr;
128  DSigInfo m_sigInfo;
129 };
130 
131 } // namespace detail
132 
134 class Data
135  : public Printable
136  , public RefRegion<detail::DataObj> {
137 public:
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 
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
340 inline std::ostream&
341 operator<<(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
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
const Name & getName() const
Definition: data.hpp:140
const DSigInfo * getSigInfo() const
Retrieve SignatureInfo.
Definition: data.hpp:184
bool decodeFrom(Encodable &&encodable)
Encode then decode as Data packet.
Definition: data.hpp:232
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
const uint8_t * begin() const
Get output begin.
Definition: encoder.hpp:34
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
void discard()
Release all space to the Region.
Definition: encoder.hpp:72
uint8_t * prependRoom(size_t size)
Make room to prepend an object.
Definition: encoder.hpp:90
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
@ Name
Definition: an.hpp:19
@ DSigValue
Definition: an.hpp:48
@ Content
Definition: an.hpp:46
@ Data
Definition: an.hpp:41
bool input(Region &region, T &target, std::istream &is=std::cin)
Read and decode from input stream.
Definition: io.hpp:15
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