ndn-cxx: NDN C++ Library 0.9.0-33-g832ea91d
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-2023 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 // [ValidityPeriod]
56 // *OtherSubelements
57
58 // InterestSignatureInfo = INTEREST-SIGNATURE-INFO-TYPE TLV-LENGTH
59 // SignatureType
60 // [KeyLocator]
61 // [SignatureNonce]
62 // [SignatureTime]
63 // [SignatureSeqNum]
64 // *OtherSubelements
65
66 size_t totalLength = 0;
67
68 // m_otherTlvs contains (if set) SignatureNonce, SignatureTime, SignatureSeqNum, ValidityPeriod,
69 // and AdditionalDescription, as well as any custom elements added by the user
70 for (const auto& block : m_otherTlvs | boost::adaptors::reversed) {
71 totalLength += prependBlock(encoder, block);
72 }
73
74 if (m_keyLocator) {
75 totalLength += m_keyLocator->wireEncode(encoder);
76 }
77
78 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::SignatureType,
79 static_cast<uint64_t>(m_type));
80
81 totalLength += encoder.prependVarNumber(totalLength);
82 totalLength += encoder.prependVarNumber(to_underlying(type));
83
84 return totalLength;
85}
86
87template size_t
88SignatureInfo::wireEncode<encoding::EncoderTag>(EncodingBuffer&, SignatureInfo::Type) const;
89
90template size_t
91SignatureInfo::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, SignatureInfo::Type) const;
92
93const Block&
95{
96 if (m_wire.hasWire())
97 return m_wire;
98
99 EncodingEstimator estimator;
100 size_t estimatedSize = wireEncode(estimator, type);
101
102 EncodingBuffer buffer(estimatedSize, 0);
103 wireEncode(buffer, type);
104
105 m_wire = buffer.block();
106 return m_wire;
107}
108
109void
111{
112 m_type = -1;
113 m_keyLocator = std::nullopt;
114 m_otherTlvs.clear();
115
116 m_wire = wire;
117 m_wire.parse();
118
119 if (m_wire.type() != to_underlying(type)) {
120 NDN_THROW(Error("SignatureInfo", m_wire.type()));
121 }
122
123 size_t lastCriticalElement = 0;
124 for (const auto& element : m_wire.elements()) {
125 switch (element.type()) {
126 case tlv::SignatureType: {
127 if (lastCriticalElement > 0) {
128 NDN_THROW(Error("SignatureType element is repeated or out-of-order"));
129 }
130 m_type = readNonNegativeIntegerAs<tlv::SignatureTypeValue>(element);
131 lastCriticalElement = 1;
132 break;
133 }
134 case tlv::KeyLocator: {
135 if (lastCriticalElement > 1) {
136 NDN_THROW(Error("KeyLocator element is repeated or out-of-order"));
137 }
138 m_keyLocator.emplace(element);
139 lastCriticalElement = 2;
140 break;
141 }
142 case tlv::SignatureNonce: {
143 // Must handle SignatureNonce specifically because we must check that its length is >0
144 if (element.value_size() < 1) {
145 NDN_THROW(Error("SignatureNonce element cannot be empty"));
146 }
147 m_otherTlvs.push_back(element);
148 break;
149 }
151 // ValidityPeriod is treated differently than other "extension" TLVs for historical reasons:
152 // It is intended to be non-critical, but its TLV-TYPE is in the critical range. Therefore,
153 // we must handle it specifically.
154 m_otherTlvs.push_back(element);
155 break;
156 default: {
157 // If the TLV-TYPE is unrecognized and critical, abort decoding
158 if (tlv::isCriticalType(element.type())) {
159 NDN_THROW(Error("Unrecognized element of critical type " + to_string(element.type())));
160 }
161 // Otherwise, store in m_otherTlvs
162 m_otherTlvs.push_back(element);
163 }
164 }
165 }
166
167 if (m_type == -1) {
168 NDN_THROW(Error("Missing SignatureType in SignatureInfo"));
169 }
170}
171
174{
175 if (type != m_type) {
176 m_type = type;
177 m_wire.reset();
178 }
179 return *this;
180}
181
182const KeyLocator&
184{
185 if (!hasKeyLocator()) {
186 NDN_THROW(Error("KeyLocator does not exist in SignatureInfo"));
187 }
188 return *m_keyLocator;
189}
190
192SignatureInfo::setKeyLocator(std::optional<KeyLocator> keyLocator)
193{
194 if (keyLocator != m_keyLocator) {
195 m_keyLocator = std::move(keyLocator);
196 m_wire.reset();
197 }
198 return *this;
199}
200
203{
204 auto it = findOtherTlv(tlv::ValidityPeriod);
205 if (it == m_otherTlvs.end()) {
206 NDN_THROW(Error("ValidityPeriod does not exist in SignatureInfo"));
207 }
208 return security::ValidityPeriod(*it);
209}
210
212SignatureInfo::setValidityPeriod(std::optional<security::ValidityPeriod> validityPeriod)
213{
214 if (!validityPeriod) {
216 }
217 else {
218 addCustomTlv(validityPeriod->wireEncode());
219 }
220 return *this;
221}
222
223std::optional<std::vector<uint8_t>>
225{
226 auto it = findOtherTlv(tlv::SignatureNonce);
227 if (it == m_otherTlvs.end()) {
228 return std::nullopt;
229 }
230 return std::vector<uint8_t>(it->value_begin(), it->value_end());
231}
232
234SignatureInfo::setNonce(std::optional<span<const uint8_t>> nonce)
235{
236 if (!nonce) {
238 }
239 else {
240 addCustomTlv(makeBinaryBlock(tlv::SignatureNonce, *nonce));
241 }
242 return *this;
243}
244
245std::optional<time::system_clock::time_point>
247{
248 auto it = findOtherTlv(tlv::SignatureTime);
249 if (it == m_otherTlvs.end()) {
250 return std::nullopt;
251 }
252 return time::fromUnixTimestamp(time::milliseconds(readNonNegativeInteger(*it)));
253}
254
256SignatureInfo::setTime(std::optional<time::system_clock::time_point> time)
257{
258 if (!time) {
260 }
261 else {
262 addCustomTlv(makeNonNegativeIntegerBlock(tlv::SignatureTime,
263 static_cast<uint64_t>(time::toUnixTimestamp(*time).count())));
264 }
265 return *this;
266}
267
268std::optional<uint64_t>
270{
271 auto it = findOtherTlv(tlv::SignatureSeqNum);
272 if (it == m_otherTlvs.end()) {
273 return std::nullopt;
274 }
275 return readNonNegativeInteger(*it);
276}
277
279SignatureInfo::setSeqNum(std::optional<uint64_t> seqNum)
280{
281 if (!seqNum) {
283 }
284 else {
285 addCustomTlv(makeNonNegativeIntegerBlock(tlv::SignatureSeqNum, *seqNum));
286 }
287 return *this;
288}
289
290std::optional<Block>
291SignatureInfo::getCustomTlv(uint32_t type) const
292{
293 auto it = findOtherTlv(type);
294 if (it == m_otherTlvs.end()) {
295 return std::nullopt;
296 }
297 return *it;
298}
299
300void
302{
303 auto existingIt = std::find_if(m_otherTlvs.begin(), m_otherTlvs.end(), [&block] (const Block& b) {
304 return b.type() == block.type();
305 });
306 if (existingIt == m_otherTlvs.end()) {
307 m_otherTlvs.push_back(std::move(block));
308 m_wire.reset();
309 }
310 else if (*existingIt != block) {
311 *existingIt = std::move(block);
312 m_wire.reset();
313 }
314}
315
316void
318{
319 auto it = std::remove_if(m_otherTlvs.begin(), m_otherTlvs.end(), [type] (const Block& block) {
320 return block.type() == type;
321 });
322
323 if (it != m_otherTlvs.end()) {
324 m_otherTlvs.erase(it, m_otherTlvs.end());
325 m_wire.reset();
326 }
327}
328
329std::vector<Block>::const_iterator
330SignatureInfo::findOtherTlv(uint32_t type) const
331{
332 return std::find_if(m_otherTlvs.begin(), m_otherTlvs.end(), [type] (const Block& block) {
333 return block.type() == type;
334 });
335}
336
337bool
339{
340 return lhs.m_type == rhs.m_type &&
341 lhs.m_keyLocator == rhs.m_keyLocator &&
342 lhs.m_otherTlvs == rhs.m_otherTlvs;
343}
344
345std::ostream&
346operator<<(std::ostream& os, const SignatureInfo& info)
347{
348 if (info.getSignatureType() == -1) {
349 return os << "Invalid SignatureInfo";
350 }
351
352 os << static_cast<tlv::SignatureTypeValue>(info.getSignatureType());
353 if (info.hasKeyLocator()) {
354 os << " " << info.getKeyLocator();
355 }
356 if (!info.m_otherTlvs.empty()) {
357 os << " { ";
358 for (const auto& block : info.m_otherTlvs) {
359 switch (block.type()) {
360 case tlv::SignatureNonce: {
361 os << "Nonce=";
362 auto nonce = *info.getNonce();
363 printHex(os, nonce, false);
364 os << " ";
365 break;
366 }
368 os << "Time=" << time::toUnixTimestamp(*info.getTime()).count() << " ";
369 break;
371 os << "SeqNum=" << *info.getSeqNum() << " ";
372 break;
374 os << "ValidityPeriod=" << info.getValidityPeriod() << " ";
375 break;
376 default:
377 os << block.type() << " ";
378 break;
379 }
380 }
381 os << "}";
382 }
383
384 return os;
385}
386
387} // 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