ndn-embeds 0.1.0
Lightweight NDN protocol stack for embedded systems
Loading...
Searching...
No Matches
data.cpp
1#include "ndn/data.hpp"
2
3#include "ndn/crypto.hpp"
4#include "ndn/tlv.hpp"
5
6#include <cstring>
7
8namespace ndn {
9
10Data::Data(const Name& name) : name_(name) {}
11
12Data& Data::setName(const Name& name) {
13 name_ = name;
14 return *this;
15}
16
17Error Data::setName(std::string_view uri) {
18 auto result = Name::fromUri(uri);
19 if (!result.ok()) {
20 return result.error;
21 }
22 name_ = result.value;
23 return Error::Success;
24}
25
26Error Data::setContent(const uint8_t* data, size_t size) {
27 if (size > DATA_MAX_CONTENT_SIZE) {
28 return Error::BufferTooSmall;
29 }
30 std::memcpy(content_.data(), data, size);
31 contentSize_ = size;
32 return Error::Success;
33}
34
35Error Data::setContent(std::string_view str) {
36 return setContent(reinterpret_cast<const uint8_t*>(str.data()), str.size());
37}
38
39Data& Data::setFreshnessPeriod(uint32_t periodMs) {
40 freshnessPeriod_ = periodMs;
41 return *this;
42}
43
44Data& Data::setFinalBlockId(uint64_t segmentNum) {
45 finalBlockId_ = segmentNum;
46 return *this;
47}
48
50 finalBlockId_.reset();
51 return *this;
52}
53
55 contentType_ = type;
56 return *this;
57}
58
60 signatureType_ = type;
61 return *this;
62}
63
65 keyLocator_ = name;
66 hasKeyLocator_ = true;
67 return *this;
68}
69
71 keyLocator_ = Name{};
72 hasKeyLocator_ = false;
73 return *this;
74}
75
76Error Data::encodeSignedPortion(uint8_t* buf, size_t bufSize, size_t& encodedLen) const {
77 TlvEncoder encoder(buf, bufSize);
78
79 // Name (required)
80 size_t nameLen = 0;
81 Error err = name_.encode(encoder.current(), encoder.remaining(), nameLen);
82 if (err != Error::Success) {
83 return err;
84 }
85 encoder.setPosition(encoder.position() + nameLen);
86
87 // MetaInfo (if ContentType, FreshnessPeriod, or FinalBlockId is present)
88 if (contentType_ != ContentType::Blob || freshnessPeriod_ || finalBlockId_) {
89 uint8_t metaInfoBuf[48];
90 TlvEncoder metaEncoder(metaInfoBuf, sizeof(metaInfoBuf));
91
92 // ContentType (only if not Blob)
93 if (contentType_ != ContentType::Blob) {
94 err = metaEncoder.writeTlvNonNegativeInteger(tlv::ContentType,
95 static_cast<uint8_t>(contentType_));
96 if (err != Error::Success) {
97 return err;
98 }
99 }
100
101 // FreshnessPeriod
102 if (freshnessPeriod_) {
103 err = metaEncoder.writeTlvNonNegativeInteger(tlv::FreshnessPeriod, *freshnessPeriod_);
104 if (err != Error::Success) {
105 return err;
106 }
107 }
108
109 // FinalBlockId (NameComponent format)
110 if (finalBlockId_) {
111 // Encode segment number as non-negative integer, wrapped in GenericNameComponent
112 uint8_t segNumBuf[9];
113 TlvEncoder segNumEncoder(segNumBuf, sizeof(segNumBuf));
114 segNumEncoder.writeNonNegativeInteger(*finalBlockId_);
115
116 // Store GenericNameComponent TLV inside FinalBlockId TLV
117 uint8_t compBuf[16];
118 TlvEncoder compEncoder(compBuf, sizeof(compBuf));
119 compEncoder.writeTlv(tlv::GenericNameComponent, segNumBuf, segNumEncoder.size());
120
121 err = metaEncoder.writeTlv(tlv::FinalBlockId, compBuf, compEncoder.size());
122 if (err != Error::Success) {
123 return err;
124 }
125 }
126
127 err = encoder.writeTlv(tlv::MetaInfo, metaInfoBuf, metaEncoder.size());
128 if (err != Error::Success) {
129 return err;
130 }
131 }
132
133 // Content
134 if (contentSize_ > 0) {
135 err = encoder.writeTlv(tlv::Content, content_.data(), contentSize_);
136 if (err != Error::Success) {
137 return err;
138 }
139 }
140
141 // SignatureInfo (SignatureType + KeyLocator)
142 uint8_t sigInfoBuf[NAME_MAX_LENGTH + 16];
143 TlvEncoder sigInfoEncoder(sigInfoBuf, sizeof(sigInfoBuf));
144 sigInfoEncoder.writeTlvNonNegativeInteger(tlv::SignatureType,
145 static_cast<uint8_t>(signatureType_));
146
147 // KeyLocator (optional)
148 if (hasKeyLocator_) {
149 uint8_t keyLocBuf[NAME_MAX_LENGTH + 4];
150 TlvEncoder keyLocEncoder(keyLocBuf, sizeof(keyLocBuf));
151 size_t keyLocNameLen = 0;
152 err = keyLocator_.encode(keyLocEncoder.current(), keyLocEncoder.remaining(), keyLocNameLen);
153 if (err != Error::Success) {
154 return err;
155 }
156 keyLocEncoder.setPosition(keyLocEncoder.position() + keyLocNameLen);
157 sigInfoEncoder.writeTlv(tlv::KeyLocator, keyLocBuf, keyLocEncoder.size());
158 }
159
160 err = encoder.writeTlv(tlv::SignatureInfo, sigInfoBuf, sigInfoEncoder.size());
161 if (err != Error::Success) {
162 return err;
163 }
164
165 encodedLen = encoder.size();
166 return Error::Success;
167}
168
170 signatureType_ = SignatureType::DigestSha256;
171
172 // Encode the signed portion
173 uint8_t signedBuf[PACKET_MAX_SIZE];
174 size_t signedLen = 0;
175 Error err = encodeSignedPortion(signedBuf, sizeof(signedBuf), signedLen);
176 if (err != Error::Success) {
177 return err;
178 }
179
180 // Compute SHA-256 digest
181 err = crypto::sha256(signedBuf, signedLen, signatureValue_.data());
182 if (err != Error::Success) {
183 return err;
184 }
185
186 signatureSize_ = SHA256_DIGEST_SIZE;
187 return Error::Success;
188}
189
190Error Data::signWithHmac(const uint8_t* key, size_t keyLen) {
191 if (key == nullptr || keyLen == 0) {
192 return Error::InvalidParam;
193 }
194
195 signatureType_ = SignatureType::SignatureHmacWithSha256;
196
197 // Encode the signed portion
198 uint8_t signedBuf[PACKET_MAX_SIZE];
199 size_t signedLen = 0;
200 Error err = encodeSignedPortion(signedBuf, sizeof(signedBuf), signedLen);
201 if (err != Error::Success) {
202 return err;
203 }
204
205 // Compute HMAC-SHA256
206 err = crypto::hmacSha256(key, keyLen, signedBuf, signedLen, signatureValue_.data());
207 if (err != Error::Success) {
208 return err;
209 }
210
211 signatureSize_ = HMAC_SHA256_SIZE;
212 return Error::Success;
213}
214
216 if (signatureType_ != SignatureType::DigestSha256) {
217 return false;
218 }
219 if (signatureSize_ != SHA256_DIGEST_SIZE) {
220 return false;
221 }
222
223 // Encode the signed portion
224 uint8_t signedBuf[PACKET_MAX_SIZE];
225 size_t signedLen = 0;
226 Error err = encodeSignedPortion(signedBuf, sizeof(signedBuf), signedLen);
227 if (err != Error::Success) {
228 return false;
229 }
230
231 // Compute SHA-256 digest
232 uint8_t computed[SHA256_DIGEST_SIZE];
233 err = crypto::sha256(signedBuf, signedLen, computed);
234 if (err != Error::Success) {
235 return false;
236 }
237
238 // Constant-time comparison
239 return crypto::constantTimeCompare(computed, signatureValue_.data(), SHA256_DIGEST_SIZE);
240}
241
242bool Data::verifyHmac(const uint8_t* key, size_t keyLen) const {
243 if (key == nullptr || keyLen == 0) {
244 return false;
245 }
246 if (signatureType_ != SignatureType::SignatureHmacWithSha256) {
247 return false;
248 }
249 if (signatureSize_ != HMAC_SHA256_SIZE) {
250 return false;
251 }
252
253 // Encode the signed portion
254 uint8_t signedBuf[PACKET_MAX_SIZE];
255 size_t signedLen = 0;
256 Error err = encodeSignedPortion(signedBuf, sizeof(signedBuf), signedLen);
257 if (err != Error::Success) {
258 return false;
259 }
260
261 // Compute HMAC-SHA256
262 uint8_t computed[HMAC_SHA256_SIZE];
263 err = crypto::hmacSha256(key, keyLen, signedBuf, signedLen, computed);
264 if (err != Error::Success) {
265 return false;
266 }
267
268 // Constant-time comparison
269 return crypto::constantTimeCompare(computed, signatureValue_.data(), HMAC_SHA256_SIZE);
270}
271
272Error Data::signWithEcdsa(const uint8_t* privKey) {
273 if (privKey == nullptr) {
274 return Error::InvalidParam;
275 }
276
277 signatureType_ = SignatureType::SignatureSha256WithEcdsa;
278
279 // Encode the signed portion
280 uint8_t signedBuf[PACKET_MAX_SIZE];
281 size_t signedLen = 0;
282 Error err = encodeSignedPortion(signedBuf, sizeof(signedBuf), signedLen);
283 if (err != Error::Success) {
284 return err;
285 }
286
287 // Generate ECDSA signature
288 err = crypto::ecdsaP256Sign(privKey, signedBuf, signedLen, signatureValue_.data(),
289 &signatureSize_);
290 return err;
291}
292
293bool Data::verifyEcdsa(const uint8_t* pubKey) const {
294 if (pubKey == nullptr) {
295 return false;
296 }
297 if (signatureType_ != SignatureType::SignatureSha256WithEcdsa) {
298 return false;
299 }
300 if (signatureSize_ == 0 || signatureSize_ > ECDSA_P256_SIG_MAX_SIZE) {
301 return false;
302 }
303
304 // Encode the signed portion
305 uint8_t signedBuf[PACKET_MAX_SIZE];
306 size_t signedLen = 0;
307 Error err = encodeSignedPortion(signedBuf, sizeof(signedBuf), signedLen);
308 if (err != Error::Success) {
309 return false;
310 }
311
312 // Verify ECDSA signature
313 return crypto::ecdsaP256Verify(pubKey, signedBuf, signedLen, signatureValue_.data(),
314 signatureSize_);
315}
316
317Error Data::encode(uint8_t* buf, size_t bufSize, size_t& encodedLen) const {
318 uint8_t valueBuf[PACKET_MAX_SIZE];
319 TlvEncoder valueEncoder(valueBuf, sizeof(valueBuf));
320
321 // Encode signed portion (Name + MetaInfo + Content + SignatureInfo)
322 size_t signedLen = 0;
323 Error err = encodeSignedPortion(valueEncoder.current(), valueEncoder.remaining(), signedLen);
324 if (err != Error::Success) {
325 return err;
326 }
327 valueEncoder.setPosition(valueEncoder.position() + signedLen);
328
329 // SignatureValue
330 err = valueEncoder.writeTlv(tlv::SignatureValue, signatureValue_.data(), signatureSize_);
331 if (err != Error::Success) {
332 return err;
333 }
334
335 // Write Data TLV header
336 const size_t valueLen = valueEncoder.size();
337 const size_t headerSize = varNumberSize(tlv::Data) + varNumberSize(valueLen);
338 const size_t totalSize = headerSize + valueLen;
339
340 if (bufSize < totalSize) {
341 return Error::BufferTooSmall;
342 }
343
344 TlvEncoder encoder(buf, bufSize);
345 err = encoder.writeType(tlv::Data);
346 if (err != Error::Success) {
347 return err;
348 }
349 err = encoder.writeLength(valueLen);
350 if (err != Error::Success) {
351 return err;
352 }
353 err = encoder.writeBytes(valueBuf, valueLen);
354 if (err != Error::Success) {
355 return err;
356 }
357
358 encodedLen = encoder.size();
359 return Error::Success;
360}
361
362Result<Data> Data::fromWire(const uint8_t* buf, size_t len) {
363 Data data;
364 TlvDecoder decoder(buf, len);
365
366 // Data TLV header
367 auto headerResult = decoder.readTlvHeader();
368 if (!headerResult.ok()) {
369 return {.value = Data{}, .error = headerResult.error};
370 }
371
372 if (headerResult.value.type != tlv::Data) {
373 return {.value = Data{}, .error = Error::InvalidPacket};
374 }
375
376 const size_t dataValueLen = headerResult.value.length;
377 const size_t dataValueEnd = decoder.position() + dataValueLen;
378
379 if (decoder.remaining() < dataValueLen) {
380 return {.value = Data{}, .error = Error::DecodeFailed};
381 }
382
383 // Parse TLVs within the Data
384 bool hasName = false;
385
386 while (decoder.position() < dataValueEnd) {
387 const size_t elementStart = decoder.position();
388
389 auto elemHeader = decoder.readTlvHeader();
390 if (!elemHeader.ok()) {
391 return {.value = Data{}, .error = elemHeader.error};
392 }
393
394 const uint32_t elemType = elemHeader.value.type;
395 const size_t elemLen = elemHeader.value.length;
396
397 if (decoder.remaining() < elemLen) {
398 return {.value = Data{}, .error = Error::DecodeFailed};
399 }
400
401 switch (elemType) {
402 case tlv::Name: {
403 decoder.setPosition(elementStart);
404 size_t bytesRead = 0;
405 auto nameResult =
406 Name::fromWire(decoder.current(), decoder.remaining(), &bytesRead);
407 if (!nameResult.ok()) {
408 return {.value = Data{}, .error = nameResult.error};
409 }
410 data.name_ = nameResult.value;
411 decoder.skip(bytesRead);
412 hasName = true;
413 break;
414 }
415
416 case tlv::MetaInfo: {
417 // Parse fields within MetaInfo
418 const size_t metaEnd = decoder.position() + elemLen;
419 while (decoder.position() < metaEnd) {
420 auto metaElemHeader = decoder.readTlvHeader();
421 if (!metaElemHeader.ok()) {
422 return {.value = Data{}, .error = metaElemHeader.error};
423 }
424
425 if (metaElemHeader.value.type == tlv::ContentType) {
426 auto ctResult = decoder.readNonNegativeInteger(metaElemHeader.value.length);
427 if (!ctResult.ok()) {
428 return {.value = Data{}, .error = ctResult.error};
429 }
430 data.contentType_ = static_cast<ContentType>(ctResult.value);
431 } else if (metaElemHeader.value.type == tlv::FreshnessPeriod) {
432 auto fpResult = decoder.readNonNegativeInteger(metaElemHeader.value.length);
433 if (!fpResult.ok()) {
434 return {.value = Data{}, .error = fpResult.error};
435 }
436 data.freshnessPeriod_ = static_cast<uint32_t>(fpResult.value);
437 } else if (metaElemHeader.value.type == tlv::FinalBlockId) {
438 // Parse NameComponent within FinalBlockId
439 auto compHeader = decoder.readTlvHeader();
440 if (!compHeader.ok()) {
441 return {.value = Data{}, .error = compHeader.error};
442 }
443 // Read the value within NameComponent as a non-negative integer
444 auto segNumResult = decoder.readNonNegativeInteger(compHeader.value.length);
445 if (!segNumResult.ok()) {
446 return {.value = Data{}, .error = segNumResult.error};
447 }
448 data.finalBlockId_ = segNumResult.value;
449 } else {
450 decoder.skip(metaElemHeader.value.length);
451 }
452 }
453 break;
454 }
455
456 case tlv::Content: {
457 if (elemLen > DATA_MAX_CONTENT_SIZE) {
458 return {.value = Data{}, .error = Error::BufferTooSmall};
459 }
460 const Error err = decoder.readBytes(data.content_.data(), elemLen);
461 if (err != Error::Success) {
462 return {.value = Data{}, .error = err};
463 }
464 data.contentSize_ = elemLen;
465 break;
466 }
467
468 case tlv::SignatureInfo: {
469 // Parse fields within SignatureInfo
470 const size_t sigInfoEnd = decoder.position() + elemLen;
471 while (decoder.position() < sigInfoEnd) {
472 auto sigInfoElemHeader = decoder.readTlvHeader();
473 if (!sigInfoElemHeader.ok()) {
474 return {.value = Data{}, .error = sigInfoElemHeader.error};
475 }
476
477 if (sigInfoElemHeader.value.type == tlv::SignatureType) {
478 auto stResult =
479 decoder.readNonNegativeInteger(sigInfoElemHeader.value.length);
480 if (!stResult.ok()) {
481 return {.value = Data{}, .error = stResult.error};
482 }
483 data.signatureType_ = static_cast<SignatureType>(stResult.value);
484 } else if (sigInfoElemHeader.value.type == tlv::KeyLocator) {
485 // Decode Name within KeyLocator
486 const size_t keyLocEnd =
487 decoder.position() + sigInfoElemHeader.value.length;
488 if (decoder.position() < keyLocEnd) {
489 size_t bytesRead = 0;
490 auto nameResult =
491 Name::fromWire(decoder.current(), decoder.remaining(), &bytesRead);
492 if (nameResult.ok()) {
493 data.keyLocator_ = nameResult.value;
494 data.hasKeyLocator_ = true;
495 }
496 decoder.setPosition(keyLocEnd);
497 }
498 } else {
499 // Ignore others
500 decoder.skip(sigInfoElemHeader.value.length);
501 }
502 }
503 break;
504 }
505
506 case tlv::SignatureValue: {
507 if (elemLen > SIGNATURE_MAX_SIZE) {
508 return {.value = Data{}, .error = Error::BufferTooSmall};
509 }
510 const Error err = decoder.readBytes(data.signatureValue_.data(), elemLen);
511 if (err != Error::Success) {
512 return {.value = Data{}, .error = err};
513 }
514 data.signatureSize_ = elemLen;
515 break;
516 }
517
518 default:
519 // Ignore unknown TLVs
520 decoder.skip(elemLen);
521 break;
522 }
523 }
524
525 if (!hasName) {
526 return {.value = Data{}, .error = Error::InvalidPacket};
527 }
528
529 return {.value = data, .error = Error::Success};
530}
531
532} // namespace ndn
NDN Data packet.
Definition data.hpp:49
Data & setFreshnessPeriod(uint32_t periodMs)
Set the FreshnessPeriod.
Definition data.cpp:39
Data & setKeyLocator(const Name &name)
Set the KeyLocator.
Definition data.cpp:64
Data & clearKeyLocator()
Clear the KeyLocator.
Definition data.cpp:70
Error signWithEcdsa(const uint8_t *privKey)
Sign with ECDSA P-256.
Definition data.cpp:272
const Name & name() const
Get the Name (const reference)
Definition data.hpp:104
Error signWithDigestSha256()
Sign with DigestSha256.
Definition data.cpp:169
Data & setContentType(ContentType type)
Set the content type.
Definition data.cpp:54
Data & setFinalBlockId(uint64_t segmentNum)
Set the FinalBlockId.
Definition data.cpp:44
bool verifyHmac(const uint8_t *key, size_t keyLen) const
Verify an HMAC-SHA256 signature.
Definition data.cpp:242
Error setContent(const uint8_t *data, size_t size)
Set binary data as content.
Definition data.cpp:26
bool verifyDigestSha256() const
Verify a DigestSha256 signature.
Definition data.cpp:215
Error encode(uint8_t *buf, size_t bufSize, size_t &encodedLen) const
Encode the Data packet to TLV wire format.
Definition data.cpp:317
Data & clearFinalBlockId()
Clear the FinalBlockId.
Definition data.cpp:49
Data & setSignatureType(SignatureType type)
Set the signature type.
Definition data.cpp:59
bool verifyEcdsa(const uint8_t *pubKey) const
Verify an ECDSA P-256 signature.
Definition data.cpp:293
static Result< Data > fromWire(const uint8_t *buf, size_t len)
Decode a Data packet from TLV wire format.
Definition data.cpp:362
Data()=default
Default constructor.
Data & setName(const Name &name)
Set the Name (supports method chaining)
Definition data.cpp:12
Error signWithHmac(const uint8_t *key, size_t keyLen)
Sign with HMAC-SHA256.
Definition data.cpp:190
NDN Name class.
Definition name.hpp:64
Error encode(uint8_t *buf, size_t bufSize, size_t &encodedLen) const
Encode the Name to TLV wire format.
Definition name.cpp:186
static Result< Name > fromWire(const uint8_t *buf, size_t len, size_t *bytesRead=nullptr)
Decode a Name from TLV wire format.
Definition name.cpp:84
static Result< Name > fromUri(std::string_view uri)
Create a Name from a URI string.
Definition name.cpp:25
TLV decoder.
Definition tlv.hpp:235
size_t position() const
Get current position.
Definition tlv.hpp:320
void setPosition(size_t pos)
Set current position.
Definition tlv.hpp:326
const uint8_t * current() const
Pointer to current position.
Definition tlv.hpp:308
Error readBytes(uint8_t *out, size_t len)
Read a specified number of bytes.
Definition tlv.cpp:239
Result< uint64_t > readNonNegativeInteger(size_t numBytes)
Read a non-negative integer of specified byte count.
Definition tlv.cpp:191
Result< TlvHeader > readTlvHeader()
Read a TLV header (Type and Length) at once.
Definition tlv.cpp:224
Error skip(size_t len)
Skip a specified number of bytes.
Definition tlv.cpp:248
size_t remaining() const
Remaining readable bytes.
Definition tlv.hpp:302
TLV encoder.
Definition tlv.hpp:116
size_t position() const
Get current position.
Definition tlv.hpp:207
Error writeLength(size_t length)
Write a TLV Length.
Definition tlv.cpp:91
void setPosition(size_t pos)
Set current position.
Definition tlv.hpp:213
Error writeTlv(uint32_t type, const uint8_t *value, size_t valueLen)
Write a complete TLV structure.
Definition tlv.cpp:104
Error writeBytes(const uint8_t *data, size_t len)
Write a byte sequence.
Definition tlv.cpp:95
size_t size() const
Current write position (= number of bytes written)
Definition tlv.hpp:189
size_t remaining() const
Remaining writable bytes.
Definition tlv.hpp:195
Error writeType(uint32_t type)
Write a TLV Type.
Definition tlv.cpp:87
uint8_t * current()
Pointer to current position.
Definition tlv.hpp:201
constexpr size_t NAME_MAX_LENGTH
Maximum Name length (bytes)
Definition common.hpp:110
ContentType
Content type.
Definition common.hpp:81
constexpr size_t DATA_MAX_CONTENT_SIZE
Maximum content size of a Data packet (bytes) ESP-NOW v2.0: max 1470 bytes - TLV overhead (approx.
Definition common.hpp:119
constexpr size_t PACKET_MAX_SIZE
Maximum packet size (ESP-NOW v2.0 compatible)
Definition common.hpp:122
Error
Error codes.
Definition common.hpp:24
NDN cryptographic utilities.
NDN Data packet.
constexpr uint32_t KeyLocator
Key locator.
Definition tlv.hpp:78
constexpr uint32_t MetaInfo
Meta information.
Definition tlv.hpp:60
constexpr uint32_t SignatureInfo
Signature info.
Definition tlv.hpp:62
constexpr uint32_t FinalBlockId
Final block ID.
Definition tlv.hpp:71
constexpr uint32_t FreshnessPeriod
Freshness period.
Definition tlv.hpp:70
constexpr uint32_t Content
Content.
Definition tlv.hpp:61
constexpr uint32_t SignatureValue
Signature value.
Definition tlv.hpp:63
constexpr uint32_t ContentType
Content type.
Definition tlv.hpp:69
constexpr uint32_t Name
Name.
Definition tlv.hpp:34
constexpr uint32_t Data
Data packet.
Definition tlv.hpp:28
constexpr uint32_t SignatureType
Signature type.
Definition tlv.hpp:77
constexpr uint32_t GenericNameComponent
Generic Name component.
Definition tlv.hpp:40
constexpr size_t SIGNATURE_MAX_SIZE
Maximum signature size (for ECDSA P-256, embedded)
Definition signature.hpp:38
constexpr size_t ECDSA_P256_SIG_MAX_SIZE
ECDSA P-256 signature max size (DER format)
Definition signature.hpp:35
constexpr size_t HMAC_SHA256_SIZE
HMAC-SHA256 size (bytes)
Definition signature.hpp:34
SignatureType
Signature type.
Definition signature.hpp:22
constexpr size_t SHA256_DIGEST_SIZE
SHA-256 digest size (bytes)
Definition signature.hpp:33
Result type template.
Definition common.hpp:147
NDN TLV (Type-Length-Value) encoding.
constexpr size_t varNumberSize(uint64_t value)
Calculate the encoded size of a VAR-NUMBER.
Definition tlv.hpp:339