blob: 7bd42eafa1e94d00271022114db8d51e3ec8dfe4 [file] [log] [blame]
Alexander Afanasyev93338872017-01-30 22:37:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2bea5c42017-08-14 20:10:32 +00002/*
Davide Pesavento0f830802018-01-16 23:58:58 -05003 * Copyright (c) 2013-2018 Regents of the University of California.
Alexander Afanasyev93338872017-01-30 22:37:00 -08004 *
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
22#include "security/v2/validation-policy-command-interest.hpp"
23#include "security/v2/validation-policy-simple-hierarchy.hpp"
24#include "security/v2/validation-policy-accept-all.hpp"
25#include "security/command-interest-signer.hpp"
26#include "security/signing-helpers.hpp"
27
28#include "boost-test.hpp"
29#include "validator-fixture.hpp"
Junxiao Shi2bea5c42017-08-14 20:10:32 +000030#include "make-interest-data.hpp"
Alexander Afanasyev93338872017-01-30 22:37:00 -080031
32#include <boost/lexical_cast.hpp>
33#include <boost/mpl/vector.hpp>
34
35namespace ndn {
36namespace security {
37namespace v2 {
38namespace tests {
39
40using namespace ndn::tests;
41
42BOOST_AUTO_TEST_SUITE(Security)
43BOOST_AUTO_TEST_SUITE(V2)
44
45class DefaultOptions
46{
47public:
48 static ValidationPolicyCommandInterest::Options
49 getOptions()
50 {
51 return {};
52 }
53};
54
55template<class T, class InnerPolicy>
56class CommandInterestPolicyWrapper : public ValidationPolicyCommandInterest
57{
58public:
59 CommandInterestPolicyWrapper()
60 : ValidationPolicyCommandInterest(make_unique<InnerPolicy>(), T::getOptions())
61 {
62 }
63};
64
65template<class T, class InnerPolicy = ValidationPolicySimpleHierarchy>
66class ValidationPolicyCommandInterestFixture : public HierarchicalValidatorFixture<CommandInterestPolicyWrapper<T, InnerPolicy>>
67{
68public:
69 ValidationPolicyCommandInterestFixture()
70 : m_signer(this->m_keyChain)
71 {
72 }
73
74 Interest
75 makeCommandInterest(const Identity& identity)
76 {
77 return m_signer.makeCommandInterest(Name(identity.getName()).append("CMD"),
78 signingByIdentity(identity));
79 }
80
81public:
82 CommandInterestSigner m_signer;
83};
84
85BOOST_FIXTURE_TEST_SUITE(TestValidationPolicyCommandInterest, ValidationPolicyCommandInterestFixture<DefaultOptions>)
86
87BOOST_AUTO_TEST_SUITE(Accepts)
88
89BOOST_AUTO_TEST_CASE(Basic)
90{
91 auto i1 = makeCommandInterest(identity);
92 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
Alexander Afanasyev31fd4672018-06-17 13:25:52 -040093 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Alexander Afanasyev93338872017-01-30 22:37:00 -080094
Davide Pesavento0f830802018-01-16 23:58:58 -050095 advanceClocks(5_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -080096 auto i2 = makeCommandInterest(identity);
97 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
Alexander Afanasyev31fd4672018-06-17 13:25:52 -040098
99 auto i3 = m_signer.makeCommandInterest(Name(identity.getName()).append("CMD"), signingWithSha256());
100 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Alexander Afanasyev93338872017-01-30 22:37:00 -0800101}
102
103BOOST_AUTO_TEST_CASE(DataPassthru)
104{
105 Data d1("/Security/V2/ValidatorFixture/Sub1");
106 m_keyChain.sign(d1);
107 VALIDATE_SUCCESS(d1, "Should succeed (fallback on inner validation policy for data)");
108}
109
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400110using ValidationPolicyAcceptAllCommands = ValidationPolicyCommandInterestFixture<DefaultOptions,
111 ValidationPolicyAcceptAll>;
112
113BOOST_FIXTURE_TEST_CASE(SignedWithSha256, ValidationPolicyAcceptAllCommands) // Bug 4635
114{
115 auto i1 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
116 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
117 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
118
119 advanceClocks(5_ms);
120 auto i2 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
121 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
122}
123
Alexander Afanasyev93338872017-01-30 22:37:00 -0800124BOOST_AUTO_TEST_SUITE_END() // Accepts
125
126BOOST_AUTO_TEST_SUITE(Rejects)
127
128BOOST_AUTO_TEST_CASE(NameTooShort)
129{
130 auto i1 = makeInterest("/name/too/short");
131 VALIDATE_FAILURE(*i1, "Should fail (name is too short)");
132}
133
134BOOST_AUTO_TEST_CASE(BadTimestamp)
135{
136 auto i1 = makeCommandInterest(identity);
137 setNameComponent(i1, command_interest::POS_TIMESTAMP, "not-timestamp");
138 VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
139}
140
141BOOST_AUTO_TEST_CASE(BadSigInfo)
142{
143 auto i1 = makeCommandInterest(identity);
144 setNameComponent(i1, command_interest::POS_SIG_INFO, "not-SignatureInfo");
145 VALIDATE_FAILURE(i1, "Should fail (signature info is missing)");
146}
147
148BOOST_AUTO_TEST_CASE(MissingKeyLocator)
149{
150 auto i1 = makeCommandInterest(identity);
Junxiao Shi605671d2017-08-26 13:41:06 +0000151 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800152 setNameComponent(i1, command_interest::POS_SIG_INFO,
153 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
154 VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
155}
156
157BOOST_AUTO_TEST_CASE(BadKeyLocatorType)
158{
159 auto i1 = makeCommandInterest(identity);
160 KeyLocator kl;
161 kl.setKeyDigest(makeBinaryBlock(tlv::KeyDigest, "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD", 8));
Junxiao Shi605671d2017-08-26 13:41:06 +0000162 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800163 sigInfo.setKeyLocator(kl);
164 setNameComponent(i1, command_interest::POS_SIG_INFO,
165 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
166 VALIDATE_FAILURE(i1, "Should fail (bad KeyLocator type)");
167}
168
169BOOST_AUTO_TEST_CASE(BadCertName)
170{
171 auto i1 = makeCommandInterest(identity);
172 KeyLocator kl;
173 kl.setName("/bad/cert/name");
Junxiao Shi605671d2017-08-26 13:41:06 +0000174 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800175 sigInfo.setKeyLocator(kl);
176 setNameComponent(i1, command_interest::POS_SIG_INFO,
177 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
178 VALIDATE_FAILURE(i1, "Should fail (bad certificate name)");
179}
180
181BOOST_AUTO_TEST_CASE(InnerPolicyReject)
182{
183 auto i1 = makeCommandInterest(otherIdentity);
184 VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
185}
186
187class GracePeriod15Sec
188{
189public:
190 static ValidationPolicyCommandInterest::Options
191 getOptions()
192 {
193 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500194 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800195 return options;
196 }
197};
198
199BOOST_FIXTURE_TEST_CASE(TimestampOutOfGracePositive, ValidationPolicyCommandInterestFixture<GracePeriod15Sec>)
200{
201 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500202 advanceClocks(16_s); // verifying at +16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800203 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
204 rewindClockAfterValidation();
205
206 auto i2 = makeCommandInterest(identity); // signed at +16s
207 VALIDATE_SUCCESS(i2, "Should succeed");
208}
209
210BOOST_FIXTURE_TEST_CASE(TimestampOutOfGraceNegative, ValidationPolicyCommandInterestFixture<GracePeriod15Sec>)
211{
212 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500213 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800214 auto i2 = makeCommandInterest(identity); // signed at +1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500215 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800216 auto i3 = makeCommandInterest(identity); // signed at +2s
217
Davide Pesavento0f830802018-01-16 23:58:58 -0500218 systemClock->advance(-18_s); // verifying at -16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800219 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
220 rewindClockAfterValidation();
221
222 // CommandInterestValidator should not remember i1's timestamp
223 VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
224 rewindClockAfterValidation();
225
226 // CommandInterestValidator should not remember i2's timestamp, and should treat i3 as initial
Davide Pesavento0f830802018-01-16 23:58:58 -0500227 advanceClocks(18_s); // verifying at +2s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800228 VALIDATE_SUCCESS(i3, "Should succeed");
229}
230
231BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
232{
233 auto i1 = makeCommandInterest(identity); // signed at 0s
234 VALIDATE_SUCCESS(i1, "Should succeed");
235
236 auto i2 = makeCommandInterest(identity); // signed at 0s
237 setNameComponent(i2, command_interest::POS_TIMESTAMP,
238 i1.getName()[command_interest::POS_TIMESTAMP]);
239 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
240
Davide Pesavento0f830802018-01-16 23:58:58 -0500241 advanceClocks(2_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800242 auto i3 = makeCommandInterest(identity); // signed at +2s
243 VALIDATE_SUCCESS(i3, "Should succeed");
244}
245
246BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
247{
248 auto i2 = makeCommandInterest(identity); // signed at 0ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500249 advanceClocks(200_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800250 auto i3 = makeCommandInterest(identity); // signed at +200ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500251 advanceClocks(900_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800252 auto i1 = makeCommandInterest(identity); // signed at +1100ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500253 advanceClocks(300_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800254 auto i4 = makeCommandInterest(identity); // signed at +1400ms
255
Davide Pesavento0f830802018-01-16 23:58:58 -0500256 systemClock->advance(-300_ms); // verifying at +1100ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800257 VALIDATE_SUCCESS(i1, "Should succeed");
258 rewindClockAfterValidation();
259
Davide Pesavento0f830802018-01-16 23:58:58 -0500260 systemClock->advance(-1100_ms); // verifying at 0ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800261 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
262 rewindClockAfterValidation();
263
264 // CommandInterestValidator should not remember i2's timestamp
Davide Pesavento0f830802018-01-16 23:58:58 -0500265 advanceClocks(200_ms); // verifying at +200ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800266 VALIDATE_FAILURE(i3, "Should fail (timestamp reordered)");
267 rewindClockAfterValidation();
268
Davide Pesavento0f830802018-01-16 23:58:58 -0500269 advanceClocks(1200_ms); // verifying at 1400ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800270 VALIDATE_SUCCESS(i4, "Should succeed");
271}
272
273BOOST_AUTO_TEST_SUITE_END() // Rejects
274
275BOOST_AUTO_TEST_SUITE(Options)
276
277template<class T>
278class GracePeriod
279{
280public:
281 static ValidationPolicyCommandInterest::Options
282 getOptions()
283 {
284 ValidationPolicyCommandInterest::Options options;
285 options.gracePeriod = time::seconds(T::value);
286 return options;
287 }
288};
289
290typedef boost::mpl::vector<
291 GracePeriod<boost::mpl::int_<0>>,
292 GracePeriod<boost::mpl::int_<-1>>
293> GraceNonPositiveValues;
294
295BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, GraceNonPositiveValues,
296 ValidationPolicyCommandInterestFixture<GracePeriod>)
297{
298 auto i1 = this->makeCommandInterest(this->identity); // signed at 0ms
299 auto i2 = this->makeCommandInterest(this->subIdentity); // signed at 0ms
300 for (auto interest : {&i1, &i2}) {
301 setNameComponent(*interest, command_interest::POS_TIMESTAMP,
302 name::Component::fromNumber(time::toUnixTimestamp(time::system_clock::now()).count()));
303 } // ensure timestamps are exactly 0ms
304
305 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
306 this->rewindClockAfterValidation();
307
Davide Pesavento0f830802018-01-16 23:58:58 -0500308 this->advanceClocks(1_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800309 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
310}
311
312class LimitedRecordsOptions
313{
314public:
315 static ValidationPolicyCommandInterest::Options
316 getOptions()
317 {
318 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500319 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800320 options.maxRecords = 3;
321 return options;
322 }
323};
324
325BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicyCommandInterestFixture<LimitedRecordsOptions>)
326{
327 Identity id1 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub1", identity);
328 this->cache.insert(id1.getDefaultKey().getDefaultCertificate());
329 Identity id2 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub2", identity);
330 this->cache.insert(id2.getDefaultKey().getDefaultCertificate());
331 Identity id3 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub3", identity);
332 this->cache.insert(id3.getDefaultKey().getDefaultCertificate());
333 Identity id4 = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub4", identity);
334 this->cache.insert(id4.getDefaultKey().getDefaultCertificate());
335
336 auto i1 = makeCommandInterest(id2);
337 auto i2 = makeCommandInterest(id3);
338 auto i3 = makeCommandInterest(id4);
339 auto i00 = makeCommandInterest(id1); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500340 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800341 auto i01 = makeCommandInterest(id1); // signed at 1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500342 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800343 auto i02 = makeCommandInterest(id1); // signed at 2s
344
345 VALIDATE_SUCCESS(i00, "Should succeed");
346 rewindClockAfterValidation();
347
348 VALIDATE_SUCCESS(i02, "Should succeed");
349 rewindClockAfterValidation();
350
351 VALIDATE_SUCCESS(i1, "Should succeed");
352 rewindClockAfterValidation();
353
354 VALIDATE_SUCCESS(i2, "Should succeed");
355 rewindClockAfterValidation();
356
357 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
358 rewindClockAfterValidation();
359
360 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
361}
362
363class UnlimitedRecordsOptions
364{
365public:
366 static ValidationPolicyCommandInterest::Options
367 getOptions()
368 {
369 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500370 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800371 options.maxRecords = -1;
372 return options;
373 }
374};
375
376BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicyCommandInterestFixture<UnlimitedRecordsOptions>)
377{
378 std::vector<Identity> identities;
379 for (int i = 0; i < 20; ++i) {
380 Identity id = this->addSubCertificate("/Security/V2/ValidatorFixture/Sub" + to_string(i), identity);
381 this->cache.insert(id.getDefaultKey().getDefaultCertificate());
382 identities.push_back(id);
383 }
384
385 auto i1 = makeCommandInterest(identities.at(0)); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500386 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800387 for (int i = 0; i < 20; ++i) {
388 auto i2 = makeCommandInterest(identities.at(i)); // signed at +1s
389
390 VALIDATE_SUCCESS(i2, "Should succeed");
391 rewindClockAfterValidation();
392 }
393 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
394}
395
396class ZeroRecordsOptions
397{
398public:
399 static ValidationPolicyCommandInterest::Options
400 getOptions()
401 {
402 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500403 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800404 options.maxRecords = 0;
405 return options;
406 }
407};
408
409BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicyCommandInterestFixture<ZeroRecordsOptions>)
410{
411 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500412 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800413 auto i2 = makeCommandInterest(identity); // signed at +1s
414 VALIDATE_SUCCESS(i2, "Should succeed");
415 rewindClockAfterValidation();
416
417 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record isn't kept");
418}
419
420class LimitedRecordLifetimeOptions
421{
422public:
423 static ValidationPolicyCommandInterest::Options
424 getOptions()
425 {
426 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500427 options.gracePeriod = 400_s;
428 options.recordLifetime = 300_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800429 return options;
430 }
431};
432
433BOOST_FIXTURE_TEST_CASE(LimitedRecordLifetime, ValidationPolicyCommandInterestFixture<LimitedRecordLifetimeOptions>)
434{
435 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500436 advanceClocks(240_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800437 auto i2 = makeCommandInterest(identity); // signed at +240s
Davide Pesavento0f830802018-01-16 23:58:58 -0500438 advanceClocks(120_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800439 auto i3 = makeCommandInterest(identity); // signed at +360s
440
Davide Pesavento0f830802018-01-16 23:58:58 -0500441 systemClock->advance(-360_s); // rewind system clock to 0s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800442 VALIDATE_SUCCESS(i1, "Should succeed");
443 rewindClockAfterValidation();
444
445 VALIDATE_SUCCESS(i3, "Should succeed");
446 rewindClockAfterValidation();
447
Davide Pesavento0f830802018-01-16 23:58:58 -0500448 advanceClocks(30_s, 301_s); // advance steady clock by 301s, and system clock to +301s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800449 VALIDATE_SUCCESS(i2, "Should succeed despite timestamp is reordered, because record has been expired");
450}
451
452class ZeroRecordLifetimeOptions
453{
454public:
455 static ValidationPolicyCommandInterest::Options
456 getOptions()
457 {
458 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500459 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800460 options.recordLifetime = time::seconds::zero();
461 return options;
462 }
463};
464
465BOOST_FIXTURE_TEST_CASE(ZeroRecordLifetime, ValidationPolicyCommandInterestFixture<ZeroRecordLifetimeOptions>)
466{
467 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500468 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800469 auto i2 = makeCommandInterest(identity); // signed at +1s
470 VALIDATE_SUCCESS(i2, "Should succeed");
471 rewindClockAfterValidation();
472
473 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record has been expired");
474}
475
476BOOST_AUTO_TEST_SUITE_END() // Options
477
478BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyCommandInterest
479BOOST_AUTO_TEST_SUITE_END() // V2
480BOOST_AUTO_TEST_SUITE_END() // Security
481
482} // namespace tests
483} // namespace v2
484} // namespace security
485} // namespace ndn