ndn-cxx 0.9.0-41-g90828595
Loading...
Searching...
No Matches
signature-info.cpp
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013-2026 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
25
26#include <algorithm>
27#include <boost/range/adaptor/reversed.hpp>
28
29namespace ndn {
30
32
33SignatureInfo::SignatureInfo(tlv::SignatureTypeValue type, std::optional<KeyLocator> keyLocator)
34 : m_type(type)
35 , m_keyLocator(std::move(keyLocator))
36{
37}
38
40{
41 wireDecode(block, type);
42}
43
44template<encoding::Tag TAG>
45size_t
47{
48 if (m_type == -1) {
49 NDN_THROW(Error("Cannot encode invalid SignatureInfo"));
50 }
51
52 // SignatureInfo = SIGNATURE-INFO-TYPE TLV-LENGTH
53 // SignatureType
54 // [KeyLocator]
55 // [SignatureTime]
56 // [ValidityPeriod]
57 // *OtherSubelement
58
59 // InterestSignatureInfo = INTEREST-SIGNATURE-INFO-TYPE TLV-LENGTH
60 // SignatureType
61 // [KeyLocator]
62 // [SignatureNonce]
63 // [SignatureTime]
64 // [SignatureSeqNum]
65 // *OtherSubelement
66
67 size_t totalLength = 0;
68
69 // m_otherTlvs contains (if set) SignatureNonce, SignatureTime, SignatureSeqNum, ValidityPeriod,
70 // and AdditionalDescription, as well as any custom elements added by the user
71 for (const auto& block : m_otherTlvs | boost::adaptors::reversed) {
72 totalLength += prependBlock(encoder, block);
73 }
74
75 if (m_keyLocator) {
76 totalLength += m_keyLocator->wireEncode(encoder);
77 }
78
79 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::SignatureType,
80 static_cast<uint64_t>(m_type));
81
82 totalLength += encoder.prependVarNumber(totalLength);
83 totalLength += encoder.prependVarNumber(to_underlying(type));
84
85 return totalLength;
86}
87
88template size_t
89SignatureInfo::wireEncode<encoding::EncoderTag>(EncodingBuffer&, SignatureInfo::Type) const;
90
91template size_t
92SignatureInfo::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, SignatureInfo::Type) const;
93
94const Block&
96{
97 if (m_wire.hasWire())
98 return m_wire;
99
100 EncodingEstimator estimator;
101 size_t estimatedSize = wireEncode(estimator, type);
102
103 EncodingBuffer buffer(estimatedSize, 0);
104 wireEncode(buffer, type);
105
106 m_wire = buffer.block();
107 return m_wire;
108}
109
110void
112{
113 m_type = -1;
114 m_keyLocator = std::nullopt;
115 m_otherTlvs.clear();
116
117 m_wire = wire;
118 m_wire.parse();
119
120 if (m_wire.type() != to_underlying(type)) {
121 NDN_THROW(Error("SignatureInfo", m_wire.type()));
122 }
123
124 size_t lastCriticalElement = 0;
125 for (const auto& element : m_wire.elements()) {
126 switch (element.type()) {
127 case tlv::SignatureType: {
128 if (lastCriticalElement > 0) {
129 NDN_THROW(Error("SignatureType element is repeated or out-of-order"));
130 }
131 m_type = readNonNegativeIntegerAs<tlv::SignatureTypeValue>(element);
132 lastCriticalElement = 1;
133 break;
134 }
135 case tlv::KeyLocator: {
136 if (lastCriticalElement > 1) {
137 NDN_THROW(Error("KeyLocator element is repeated or out-of-order"));
138 }
139 m_keyLocator.emplace(element);
140 lastCriticalElement = 2;
141 break;
142 }
143 case tlv::SignatureNonce: {
144 // Must handle SignatureNonce specifically because we must check that its length is >0
145 if (element.value_size() < 1) {
146 NDN_THROW(Error("SignatureNonce element cannot be empty"));
147 }
148 m_otherTlvs.push_back(element);
149 break;
150 }
152 // ValidityPeriod is treated differently than other "extension" TLVs for historical reasons:
153 // It is intended to be non-critical, but its TLV-TYPE is in the critical range. Therefore,
154 // we must handle it specifically.
155 m_otherTlvs.push_back(element);
156 break;
157 default: {
158 // If the TLV-TYPE is unrecognized and critical, abort decoding
159 if (tlv::isCriticalType(element.type())) {
160 NDN_THROW(Error("Unrecognized element of critical type " + to_string(element.type())));
161 }
162 // Otherwise, store in m_otherTlvs
163 m_otherTlvs.push_back(element);
164 }
165 }
166 }
167
168 if (m_type == -1) {
169 NDN_THROW(Error("Missing SignatureType in SignatureInfo"));
170 }
171}
172
175{
176 if (type != m_type) {
177 m_type = type;
178 m_wire.reset();
179 }
180 return *this;
181}
182
183const KeyLocator&
185{
186 if (!hasKeyLocator()) {
187 NDN_THROW(Error("KeyLocator does not exist in SignatureInfo"));
188 }
189 return *m_keyLocator;
190}
191
193SignatureInfo::setKeyLocator(std::optional<KeyLocator> keyLocator)
194{
195 if (keyLocator != m_keyLocator) {
196 m_keyLocator = std::move(keyLocator);
197 m_wire.reset();
198 }
199 return *this;
200}
201
204{
205 auto it = findOtherTlv(tlv::ValidityPeriod);
206 if (it == m_otherTlvs.end()) {
207 NDN_THROW(Error("ValidityPeriod does not exist in SignatureInfo"));
208 }
209 return security::ValidityPeriod(*it);
210}
211
213SignatureInfo::setValidityPeriod(std::optional<security::ValidityPeriod> validityPeriod)
214{
215 if (!validityPeriod) {
217 }
218 else {
219 addCustomTlv(validityPeriod->wireEncode());
220 }
221 return *this;
222}
223
224std::optional<std::vector<uint8_t>>
226{
227 auto it = findOtherTlv(tlv::SignatureNonce);
228 if (it == m_otherTlvs.end()) {
229 return std::nullopt;
230 }
231 return std::vector<uint8_t>(it->value_begin(), it->value_end());
232}
233
235SignatureInfo::setNonce(std::optional<span<const uint8_t>> nonce)
236{
237 if (!nonce) {
239 }
240 else {
241 addCustomTlv(makeBinaryBlock(tlv::SignatureNonce, *nonce));
242 }
243 return *this;
244}
245
246std::optional<time::system_clock::time_point>
248{
249 auto it = findOtherTlv(tlv::SignatureTime);
250 if (it == m_otherTlvs.end()) {
251 return std::nullopt;
252 }
253 return time::fromUnixTimestamp(time::milliseconds(readNonNegativeInteger(*it)));
254}
255
257SignatureInfo::setTime(std::optional<time::system_clock::time_point> time)
258{
259 if (!time) {
261 }
262 else {
263 addCustomTlv(makeNonNegativeIntegerBlock(tlv::SignatureTime,
264 static_cast<uint64_t>(time::toUnixTimestamp(*time).count())));
265 }
266 return *this;
267}
268
269std::optional<uint64_t>
271{
272 auto it = findOtherTlv(tlv::SignatureSeqNum);
273 if (it == m_otherTlvs.end()) {
274 return std::nullopt;
275 }
276 return readNonNegativeInteger(*it);
277}
278
280SignatureInfo::setSeqNum(std::optional<uint64_t> seqNum)
281{
282 if (!seqNum) {
284 }
285 else {
286 addCustomTlv(makeNonNegativeIntegerBlock(tlv::SignatureSeqNum, *seqNum));
287 }
288 return *this;
289}
290
291std::optional<Block>
292SignatureInfo::getCustomTlv(uint32_t type) const
293{
294 auto it = findOtherTlv(type);
295 if (it == m_otherTlvs.end()) {
296 return std::nullopt;
297 }
298 return *it;
299}
300
301void
303{
304 auto existingIt = std::find_if(m_otherTlvs.begin(), m_otherTlvs.end(), [&block] (const Block& b) {
305 return b.type() == block.type();
306 });
307 if (existingIt == m_otherTlvs.end()) {
308 m_otherTlvs.push_back(std::move(block));
309 m_wire.reset();
310 }
311 else if (*existingIt != block) {
312 *existingIt = std::move(block);
313 m_wire.reset();
314 }
315}
316
317void
319{
320 auto it = std::remove_if(m_otherTlvs.begin(), m_otherTlvs.end(), [type] (const Block& block) {
321 return block.type() == type;
322 });
323
324 if (it != m_otherTlvs.end()) {
325 m_otherTlvs.erase(it, m_otherTlvs.end());
326 m_wire.reset();
327 }
328}
329
330std::vector<Block>::const_iterator
331SignatureInfo::findOtherTlv(uint32_t type) const
332{
333 return std::find_if(m_otherTlvs.begin(), m_otherTlvs.end(), [type] (const Block& block) {
334 return block.type() == type;
335 });
336}
337
338bool
340{
341 return lhs.m_type == rhs.m_type &&
342 lhs.m_keyLocator == rhs.m_keyLocator &&
343 lhs.m_otherTlvs == rhs.m_otherTlvs;
344}
345
346std::ostream&
347operator<<(std::ostream& os, const SignatureInfo& info)
348{
349 if (info.getSignatureType() == -1) {
350 return os << "Invalid SignatureInfo";
351 }
352
353 os << static_cast<tlv::SignatureTypeValue>(info.getSignatureType());
354 if (info.hasKeyLocator()) {
355 os << " " << info.getKeyLocator();
356 }
357 if (!info.m_otherTlvs.empty()) {
358 os << " { ";
359 for (const auto& block : info.m_otherTlvs) {
360 switch (block.type()) {
361 case tlv::SignatureNonce: {
362 os << "Nonce=";
363 auto nonce = *info.getNonce();
364 printHex(os, nonce, false);
365 os << " ";
366 break;
367 }
369 os << "Time=" << time::toUnixTimestamp(*info.getTime()).count() << " ";
370 break;
372 os << "SeqNum=" << *info.getSeqNum() << " ";
373 break;
375 os << "ValidityPeriod=" << info.getValidityPeriod() << " ";
376 break;
377 default:
378 os << block.type() << " ";
379 break;
380 }
381 }
382 os << "}";
383 }
384
385 return os;
386}
387
388} // namespace ndn
Represents a TLV element of the NDN packet format.
Definition block.hpp:45
const element_container & elements() const noexcept
Get container of sub-elements.
Definition block.hpp:424
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition block.hpp:205
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition block.hpp:275
void reset() noexcept
Reset the Block to a default-constructed state.
Definition block.cpp:293
void parse() const
Parse TLV-VALUE into sub-elements.
Definition block.cpp:326
Represents a SignatureInfo or InterestSignatureInfo TLV element.
size_t wireEncode(EncodingImpl< TAG > &encoder, Type type=Type::Data) const
Fast encoding or block size estimation.
SignatureInfo & setSignatureType(tlv::SignatureTypeValue type)
Set the SignatureType.
SignatureInfo & setSeqNum(std::optional< uint64_t > seqNum)
Append or replace SignatureSeqNum.
SignatureInfo & setNonce(std::optional< span< const uint8_t > > nonce)
Append or replace SignatureNonce.
std::optional< uint64_t > getSeqNum() const
Get SignatureSeqNum.
std::optional< std::vector< uint8_t > > getNonce() const
Get SignatureNonce.
void addCustomTlv(Block block)
Append an arbitrary TLV element to this SignatureInfo.
security::ValidityPeriod getValidityPeriod() const
Get the ValidityPeriod element.
int32_t getSignatureType() const noexcept
Get the SignatureType.
SignatureInfo & setTime(std::optional< time::system_clock::time_point > time=time::system_clock::now())
Append or replace SignatureTime.
SignatureInfo & setValidityPeriod(std::optional< security::ValidityPeriod > validityPeriod)
Append, replace, or remove the ValidityPeriod element.
bool hasKeyLocator() const noexcept
Check if KeyLocator is present.
void removeCustomTlv(uint32_t type)
Remove all arbitrary TLV elements with the specified TLV-TYPE from this SignatureInfo.
void wireDecode(const Block &wire, Type type=Type::Data)
Decode from wire format.
std::optional< Block > getCustomTlv(uint32_t type) const
Get first custom TLV element with the specified TLV-TYPE.
std::optional< time::system_clock::time_point > getTime() const
Get SignatureTime.
SignatureInfo & setKeyLocator(std::optional< KeyLocator > keyLocator)
Set or unset the KeyLocator element.
const KeyLocator & getKeyLocator() const
Get the KeyLocator element.
Represents a ValidityPeriod TLV element.
#define NDN_THROW(e)
Definition exception.hpp:56
constexpr system_clock::time_point fromUnixTimestamp(system_clock::duration d)
Convert UNIX timestamp to system_clock::time_point.
Definition time.hpp:274
constexpr Duration toUnixTimestamp(const system_clock::time_point &tp)
Convert system_clock::time_point to UNIX timestamp.
Definition time.hpp:265
::boost::chrono::milliseconds milliseconds
Definition time.hpp:52
@ SignatureSeqNum
Definition tlv.hpp:105
@ SignatureNonce
Definition tlv.hpp:103
@ SignatureType
Definition tlv.hpp:100
@ SignatureTime
Definition tlv.hpp:104
@ KeyLocator
Definition tlv.hpp:101
@ ValidityPeriod
Definition tlv.hpp:107
constexpr bool isCriticalType(uint32_t type) noexcept
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition tlv.hpp:162
SignatureTypeValue
SignatureType values.
Definition tlv.hpp:127
Definition data.cpp:25
void printHex(std::ostream &os, uint64_t num, bool wantUpperCase)
Output the hex representation of num to the output stream os.
bool operator==(const Data &lhs, const Data &rhs)
Definition data.cpp:367
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition data.cpp:377
constexpr std::underlying_type_t< T > to_underlying(T val) noexcept
Definition backports.hpp:44
STL namespace.
SignatureInfo info