blob: 58f502eec087b56724b64010579480556acb336d [file] [log] [blame]
Eric Newberry1caa6342020-08-23 19:29:08 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Davide Pesaventoaee2ada2022-02-18 14:43:02 -05003 * Copyright (c) 2013-2022 Regents of the University of California.
Eric Newberry1caa6342020-08-23 19:29:08 -07004 *
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 "ndn-cxx/security/validation-policy-signed-interest.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050023
Eric Newberry1caa6342020-08-23 19:29:08 -070024#include "ndn-cxx/security/interest-signer.hpp"
Eric Newberry1caa6342020-08-23 19:29:08 -070025#include "ndn-cxx/security/validation-policy-accept-all.hpp"
26#include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
27
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050028#include "tests/test-common.hpp"
Eric Newberry1caa6342020-08-23 19:29:08 -070029#include "tests/unit/security/validator-fixture.hpp"
30
Eric Newberry1caa6342020-08-23 19:29:08 -070031#include <boost/mpl/vector.hpp>
32
33namespace ndn {
34namespace security {
35inline namespace v2 {
36namespace tests {
37
38using namespace ndn::tests;
39
40BOOST_AUTO_TEST_SUITE(Security)
41
Davide Pesavento2acce252022-09-08 22:03:03 -040042struct SignedInterestDefaultOptions
Eric Newberry1caa6342020-08-23 19:29:08 -070043{
Eric Newberry1caa6342020-08-23 19:29:08 -070044 static ValidationPolicySignedInterest::Options
45 getOptions()
46 {
47 return {};
48 }
49};
50
51template<class T, class InnerPolicy>
52class SignedInterestPolicyWrapper : public ValidationPolicySignedInterest
53{
54public:
55 SignedInterestPolicyWrapper()
56 : ValidationPolicySignedInterest(make_unique<InnerPolicy>(), T::getOptions())
57 {
58 }
59};
60
61template<class T, class InnerPolicy = ValidationPolicySimpleHierarchy>
62class ValidationPolicySignedInterestFixture
63 : public HierarchicalValidatorFixture<SignedInterestPolicyWrapper<T, InnerPolicy>>
64{
Davide Pesavento2acce252022-09-08 22:03:03 -040065protected:
Eric Newberry1caa6342020-08-23 19:29:08 -070066 Interest
67 makeSignedInterest(const Identity& identity,
68 uint32_t signingFlags = InterestSigner::WantNonce | InterestSigner::WantTime)
69 {
70 Interest i(Name(identity.getName()).append("CMD"));
Eric Newberry1caa6342020-08-23 19:29:08 -070071 m_signer.makeSignedInterest(i, signingByIdentity(identity), signingFlags);
72 return i;
73 }
74
Davide Pesavento2acce252022-09-08 22:03:03 -040075protected:
76 InterestSigner m_signer{this->m_keyChain};
Eric Newberry1caa6342020-08-23 19:29:08 -070077
78 static constexpr uint32_t WantAll = InterestSigner::WantNonce |
79 InterestSigner::WantTime |
80 InterestSigner::WantSeqNum;
81};
82
83BOOST_FIXTURE_TEST_SUITE(TestValidationPolicySignedInterest,
84 ValidationPolicySignedInterestFixture<SignedInterestDefaultOptions>)
85
Davide Pesavento2acce252022-09-08 22:03:03 -040086BOOST_AUTO_TEST_CASE(Basic)
Eric Newberry1caa6342020-08-23 19:29:08 -070087{
88 auto i1 = makeSignedInterest(identity, WantAll);
89 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
90 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -040091 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -070092
93 advanceClocks(5_ms);
94 auto i2 = makeSignedInterest(identity, WantAll);
95 VALIDATE_SUCCESS(i2, "Should succeed (timestamp and sequence number larger than previous)");
96
97 Interest i3(Name(identity.getName()).append("CMD"));
Eric Newberry1caa6342020-08-23 19:29:08 -070098 m_signer.makeSignedInterest(i3, signingWithSha256());
99 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400100 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700101}
102
103BOOST_AUTO_TEST_CASE(DataPassthrough)
104{
105 Data d1("/Security/ValidatorFixture/Sub1");
106 m_keyChain.sign(d1);
107 VALIDATE_SUCCESS(d1, "Should succeed (fallback on inner validation policy for data)");
108}
109
110BOOST_AUTO_TEST_CASE(InnerPolicyReject)
111{
112 auto i1 = makeSignedInterest(otherIdentity);
113 VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400114 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
Eric Newberry1caa6342020-08-23 19:29:08 -0700115}
116
Davide Pesavento2acce252022-09-08 22:03:03 -0400117template<ssize_t count>
118struct MaxRecordCount
Eric Newberry1caa6342020-08-23 19:29:08 -0700119{
Eric Newberry1caa6342020-08-23 19:29:08 -0700120 static ValidationPolicySignedInterest::Options
121 getOptions()
122 {
123 ValidationPolicySignedInterest::Options options;
124 options.timestampGracePeriod = 15_s;
Davide Pesavento2acce252022-09-08 22:03:03 -0400125 options.maxRecordCount = count;
Eric Newberry1caa6342020-08-23 19:29:08 -0700126 return options;
127 }
128};
129
Davide Pesavento2acce252022-09-08 22:03:03 -0400130BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<3>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700131{
132 Identity id1 = addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
133 cache.insert(id1.getDefaultKey().getDefaultCertificate());
134 Identity id2 = addSubCertificate("/Security/ValidatorFixture/Sub2", identity);
135 cache.insert(id2.getDefaultKey().getDefaultCertificate());
136 Identity id3 = addSubCertificate("/Security/ValidatorFixture/Sub3", identity);
137 cache.insert(id3.getDefaultKey().getDefaultCertificate());
138 Identity id4 = addSubCertificate("/Security/ValidatorFixture/Sub4", identity);
139 cache.insert(id4.getDefaultKey().getDefaultCertificate());
140
141 auto i1 = makeSignedInterest(id2);
142 auto i2 = makeSignedInterest(id3);
143 auto i3 = makeSignedInterest(id4);
144 auto i00 = makeSignedInterest(id1); // signed at 0s
145 advanceClocks(1_s);
146 auto i01 = makeSignedInterest(id1); // signed at 1s
147 advanceClocks(1_s);
148 auto i02 = makeSignedInterest(id1); // signed at 2s
149
150 VALIDATE_SUCCESS(i00, "Should succeed");
151 rewindClockAfterValidation();
152
153 VALIDATE_SUCCESS(i02, "Should succeed");
154 rewindClockAfterValidation();
155
156 VALIDATE_SUCCESS(i1, "Should succeed");
157 rewindClockAfterValidation();
158
159 VALIDATE_SUCCESS(i2, "Should succeed");
160 rewindClockAfterValidation();
161
162 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
163 rewindClockAfterValidation();
164
165 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
166}
167
Davide Pesavento2acce252022-09-08 22:03:03 -0400168BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<-1>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700169{
170 std::vector<Identity> identities;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500171 for (size_t i = 0; i < 20; ++i) {
Eric Newberry1caa6342020-08-23 19:29:08 -0700172 Identity id = addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
173 cache.insert(id.getDefaultKey().getDefaultCertificate());
174 identities.push_back(id);
175 }
176
177 auto i1 = makeSignedInterest(identities.at(0)); // signed at 0s
178 advanceClocks(1_s);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500179 for (size_t i = 0; i < 20; ++i) {
Eric Newberry1caa6342020-08-23 19:29:08 -0700180 auto i2 = makeSignedInterest(identities.at(i)); // signed at +1s
Eric Newberry1caa6342020-08-23 19:29:08 -0700181 VALIDATE_SUCCESS(i2, "Should succeed");
182 rewindClockAfterValidation();
183 }
Davide Pesavento2acce252022-09-08 22:03:03 -0400184
Eric Newberry1caa6342020-08-23 19:29:08 -0700185 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400186 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700187}
188
Davide Pesavento2acce252022-09-08 22:03:03 -0400189BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<0>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700190{
191 auto i1 = makeSignedInterest(identity); // signed at 0s
192 advanceClocks(1_s);
193 auto i2 = makeSignedInterest(identity); // signed at +1s
194 VALIDATE_SUCCESS(i2, "Should succeed");
195 rewindClockAfterValidation();
196
197 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp reordering, as records aren't kept");
198}
199
200BOOST_AUTO_TEST_SUITE(TimestampValidation)
201
202BOOST_AUTO_TEST_CASE(MissingTimestamp)
203{
204 auto i1 = makeSignedInterest(identity, InterestSigner::WantSeqNum);
205 VALIDATE_FAILURE(i1, "Should fail (timestamp missing)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400206 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700207}
208
Davide Pesavento2acce252022-09-08 22:03:03 -0400209struct DisabledTimestampValidationOptions
Eric Newberry1caa6342020-08-23 19:29:08 -0700210{
Eric Newberry1caa6342020-08-23 19:29:08 -0700211 static ValidationPolicySignedInterest::Options
212 getOptions()
213 {
214 ValidationPolicySignedInterest::Options options;
215 options.shouldValidateTimestamps = false;
216 return options;
217 }
218};
219
220BOOST_FIXTURE_TEST_CASE(Disabled,
221 ValidationPolicySignedInterestFixture<DisabledTimestampValidationOptions>)
222{
223 auto i1 = makeSignedInterest(identity); // signed at 0ms
224 advanceClocks(100_ms);
225 VALIDATE_SUCCESS(i1, "Should succeed");
226
227 auto i2 = makeSignedInterest(identity); // signed at +100ms
228 // Set i2 to have same timestamp as i1
229 auto si2 = i2.getSignatureInfo();
230 si2->setTime(i2.getSignatureInfo()->getTime());
231 i2.setSignatureInfo(*si2);
232 VALIDATE_SUCCESS(i2, "Should succeed");
233}
234
Davide Pesavento2acce252022-09-08 22:03:03 -0400235template<int secs>
236struct GracePeriodSeconds
Eric Newberry1caa6342020-08-23 19:29:08 -0700237{
Eric Newberry1caa6342020-08-23 19:29:08 -0700238 static ValidationPolicySignedInterest::Options
239 getOptions()
240 {
241 ValidationPolicySignedInterest::Options options;
Davide Pesavento2acce252022-09-08 22:03:03 -0400242 options.timestampGracePeriod = time::seconds(secs);
Eric Newberry1caa6342020-08-23 19:29:08 -0700243 return options;
244 }
245};
246
Davide Pesavento2acce252022-09-08 22:03:03 -0400247BOOST_FIXTURE_TEST_CASE(TimestampTooOld, ValidationPolicySignedInterestFixture<GracePeriodSeconds<15>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700248{
249 auto i1 = makeSignedInterest(identity); // signed at 0s
250 advanceClocks(16_s); // verifying at +16s
251 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400252 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700253 rewindClockAfterValidation();
254
255 auto i2 = makeSignedInterest(identity); // signed at +16s
256 VALIDATE_SUCCESS(i2, "Should succeed");
257}
258
Davide Pesavento2acce252022-09-08 22:03:03 -0400259BOOST_FIXTURE_TEST_CASE(TimestampTooNew, ValidationPolicySignedInterestFixture<GracePeriodSeconds<15>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700260{
261 auto i1 = makeSignedInterest(identity); // signed at 0s
262 advanceClocks(1_s);
263 auto i2 = makeSignedInterest(identity); // signed at +1s
264 advanceClocks(1_s);
265 auto i3 = makeSignedInterest(identity); // signed at +2s
266
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500267 m_systemClock->advance(-18_s); // verifying at -16s
Eric Newberry1caa6342020-08-23 19:29:08 -0700268 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400269 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700270 rewindClockAfterValidation();
271
272 // SignedInterestValidator should not remember i1's timestamp
273 VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400274 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700275 rewindClockAfterValidation();
276
277 // SignedInterestValidator should not remember i2's timestamp, and should treat i3 as initial
278 advanceClocks(18_s); // verifying at +2s
279 VALIDATE_SUCCESS(i3, "Should succeed");
280}
281
282BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
283{
284 auto i1 = makeSignedInterest(identity); // signed at 0s
285 VALIDATE_SUCCESS(i1, "Should succeed");
286
287 auto i2 = makeSignedInterest(identity); // signed at 0s
288 auto si2 = i2.getSignatureInfo();
289 si2->setTime(i1.getSignatureInfo()->getTime());
290 i2.setSignatureInfo(*si2);
291 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400292 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700293
294 advanceClocks(2_s);
295 auto i3 = makeSignedInterest(identity); // signed at +2s
296 VALIDATE_SUCCESS(i3, "Should succeed");
297}
298
299BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
300{
301 auto i2 = makeSignedInterest(identity); // signed at 0ms
302 advanceClocks(200_ms);
303 auto i3 = makeSignedInterest(identity); // signed at +200ms
304 advanceClocks(900_ms);
305 auto i1 = makeSignedInterest(identity); // signed at +1100ms
306 advanceClocks(300_ms);
307 auto i4 = makeSignedInterest(identity); // signed at +1400ms
308
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500309 m_systemClock->advance(-300_ms); // verifying at +1100ms
Eric Newberry1caa6342020-08-23 19:29:08 -0700310 VALIDATE_SUCCESS(i1, "Should succeed");
311 rewindClockAfterValidation();
312
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500313 m_systemClock->advance(-1100_ms); // verifying at 0ms
Eric Newberry1caa6342020-08-23 19:29:08 -0700314 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400315 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700316 rewindClockAfterValidation();
317
318 // SignedInterestValidator should not remember i2's timestamp
319 advanceClocks(200_ms); // verifying at +200ms
320 VALIDATE_FAILURE(i3, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400321 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700322 rewindClockAfterValidation();
323
324 advanceClocks(1200_ms); // verifying at 1400ms
325 VALIDATE_SUCCESS(i4, "Should succeed");
326}
327
Davide Pesavento2acce252022-09-08 22:03:03 -0400328using NonPositiveGracePeriods = boost::mpl::vector<
329 GracePeriodSeconds<0>,
330 GracePeriodSeconds<-1>
331>;
Eric Newberry1caa6342020-08-23 19:29:08 -0700332
Davide Pesavento2acce252022-09-08 22:03:03 -0400333BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, NonPositiveGracePeriods,
Eric Newberry1caa6342020-08-23 19:29:08 -0700334 ValidationPolicySignedInterestFixture<GracePeriod>)
335{
336 auto i1 = this->makeSignedInterest(this->identity); // signed at 0ms
337 auto i2 = this->makeSignedInterest(this->subIdentity); // signed at 0ms
338 // ensure timestamps are exactly 0ms
339 for (auto interest : {&i1, &i2}) {
340 auto si = interest->getSignatureInfo();
341 si->setTime(time::system_clock::now());
342 interest->setSignatureInfo(*si);
343 }
344
345 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
346 this->rewindClockAfterValidation();
347
348 this->advanceClocks(1_ms);
349 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
Davide Pesavento2acce252022-09-08 22:03:03 -0400350 BOOST_TEST(this->lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700351}
352
353BOOST_AUTO_TEST_SUITE_END() // TimestampValidation
354
355BOOST_AUTO_TEST_SUITE(SeqNumValidation)
356
357// By default, sequence number validation is disabled
358BOOST_AUTO_TEST_CASE(Disabled)
359{
360 auto i1 = makeSignedInterest(identity, WantAll); // signed at 0ms
361 VALIDATE_SUCCESS(i1, "Should succeed");
362
363 auto i2 = makeSignedInterest(identity, WantAll); // signed at +100ms
364 // Set i2 to have same seq num as i1
365 auto si2 = i2.getSignatureInfo();
366 si2->setSeqNum(i2.getSignatureInfo()->getSeqNum());
367 i2.setSignatureInfo(*si2);
368 VALIDATE_SUCCESS(i2, "Should succeed");
369}
370
Davide Pesavento2acce252022-09-08 22:03:03 -0400371struct SeqNumValidationOptions
Eric Newberry1caa6342020-08-23 19:29:08 -0700372{
Eric Newberry1caa6342020-08-23 19:29:08 -0700373 static ValidationPolicySignedInterest::Options
374 getOptions()
375 {
376 ValidationPolicySignedInterest::Options options;
377 options.shouldValidateSeqNums = true;
378 return options;
379 }
380};
381
382BOOST_FIXTURE_TEST_CASE(MissingSeqNum,
383 ValidationPolicySignedInterestFixture<SeqNumValidationOptions>)
384{
385 auto i1 = makeSignedInterest(identity, InterestSigner::WantTime);
386 VALIDATE_FAILURE(i1, "Should fail (sequence number missing");
Davide Pesavento2acce252022-09-08 22:03:03 -0400387 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700388}
389
390BOOST_FIXTURE_TEST_CASE(SeqNumReorder,
391 ValidationPolicySignedInterestFixture<SeqNumValidationOptions>)
392{
393 auto i1 = makeSignedInterest(identity, WantAll); // seq num is i
394 VALIDATE_SUCCESS(i1, "Should succeed");
395
396 auto i2 = makeSignedInterest(identity, WantAll); // seq num is i+1
397 auto si2 = i2.getSignatureInfo();
398 si2->setSeqNum(i1.getSignatureInfo()->getSeqNum());
399 i2.setSignatureInfo(*si2);
400 VALIDATE_FAILURE(i2, "Should fail (sequence number reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400401 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700402
403 auto i3 = makeSignedInterest(identity, WantAll); // seq num is i+2
404 VALIDATE_SUCCESS(i3, "Should succeed");
405}
406
407BOOST_AUTO_TEST_SUITE_END() // SeqNumValidation
408
409BOOST_AUTO_TEST_SUITE(NonceValidation)
410
411BOOST_AUTO_TEST_CASE(MissingNonce)
412{
413 auto i1 = makeSignedInterest(identity, InterestSigner::WantTime); // Specifically exclude nonce
414 VALIDATE_FAILURE(i1, "Should fail (nonce missing)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400415 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700416}
417
418BOOST_AUTO_TEST_CASE(DuplicateNonce)
419{
420 auto i1 = makeSignedInterest(identity, WantAll);
421 VALIDATE_SUCCESS(i1, "Should succeed");
422
423 auto i2 = makeSignedInterest(identity, WantAll);
424 auto si2 = i2.getSignatureInfo();
425 si2->setNonce(i1.getSignatureInfo()->getNonce());
426 i2.setSignatureInfo(*si2);
427 VALIDATE_FAILURE(i2, "Should fail (duplicate nonce)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400428 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700429
430 auto i3 = makeSignedInterest(identity, WantAll);
431 // On the off chance that the generated nonce is identical to i1
432 while (i3.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce()) {
433 i3 = makeSignedInterest(identity, WantAll);
434 }
435 VALIDATE_SUCCESS(i3, "Should succeed");
436}
437
Davide Pesavento2acce252022-09-08 22:03:03 -0400438struct DisabledNonceValidationOptions
Eric Newberry1caa6342020-08-23 19:29:08 -0700439{
Eric Newberry1caa6342020-08-23 19:29:08 -0700440 static ValidationPolicySignedInterest::Options
441 getOptions()
442 {
443 ValidationPolicySignedInterest::Options options;
444 options.shouldValidateNonces = false;
445 return options;
446 }
447};
448
449BOOST_FIXTURE_TEST_CASE(Disabled,
450 ValidationPolicySignedInterestFixture<DisabledNonceValidationOptions>)
451{
452 auto i1 = makeSignedInterest(identity, WantAll ^ InterestSigner::WantNonce);
453 VALIDATE_SUCCESS(i1, "Should succeed");
454
455 // Ensure still works when a nonce is present
456 auto i2 = makeSignedInterest(identity, WantAll);
457 VALIDATE_SUCCESS(i2, "Should succeed");
458
459 // Ensure a duplicate still succeeds
460 auto i3 = makeSignedInterest(identity, WantAll);
461 auto si3 = i3.getSignatureInfo();
462 si3->setNonce(i2.getSignatureInfo()->getNonce());
463 i3.setSignatureInfo(*si3);
464 m_keyChain.sign(i3, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
465 .setSignatureInfo(*si3));
466 VALIDATE_SUCCESS(i3, "Should succeed");
467}
468
Davide Pesavento2acce252022-09-08 22:03:03 -0400469struct NonceLimit2Options
Eric Newberry1caa6342020-08-23 19:29:08 -0700470{
Eric Newberry1caa6342020-08-23 19:29:08 -0700471 static ValidationPolicySignedInterest::Options
472 getOptions()
473 {
474 ValidationPolicySignedInterest::Options options;
475 options.shouldValidateTimestamps = false;
476 options.shouldValidateSeqNums = false;
477 options.maxNonceRecordCount = 2;
478 return options;
479 }
480};
481
482BOOST_FIXTURE_TEST_CASE(NonceRecordLimit,
483 ValidationPolicySignedInterestFixture<NonceLimit2Options>)
484{
485 auto i1 = makeSignedInterest(identity, WantAll);
486 VALIDATE_SUCCESS(i1, "Should succeed");
487
488 auto i2 = makeSignedInterest(identity, WantAll);
489 // On the off chance that the generated nonce is identical to i1
490 while (i2.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce()) {
491 i2 = makeSignedInterest(identity, WantAll);
492 }
493 VALIDATE_SUCCESS(i2, "Should succeed");
494
495 auto i3 = makeSignedInterest(identity, WantAll);
496 auto si3 = i3.getSignatureInfo();
497 si3->setNonce(i1.getSignatureInfo()->getNonce());
498 i3.setSignatureInfo(*si3);
499 m_keyChain.sign(i3, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
500 .setSignatureInfo(*si3));
501 VALIDATE_FAILURE(i3, "Should fail (duplicate nonce)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400502 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700503
504 // Pop i1's nonce off the list
505 auto i4 = makeSignedInterest(identity, WantAll);
506 // On the off chance that the generated nonce is identical to i1 or i2
507 while (i4.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce() ||
508 i4.getSignatureInfo()->getNonce() == i2.getSignatureInfo()->getNonce()) {
509 i4 = makeSignedInterest(identity, WantAll);
510 }
511 VALIDATE_SUCCESS(i4, "Should succeed");
512
513 // Now i3 should succeed because i1's nonce has been popped off the list
514 auto i5 = makeSignedInterest(identity, WantAll);
515 auto si5 = i5.getSignatureInfo();
516 si5->setNonce(i1.getSignatureInfo()->getNonce());
517 i5.setSignatureInfo(*si5);
518 m_keyChain.sign(i5, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
519 .setSignatureInfo(*si5));
520 VALIDATE_SUCCESS(i5, "Should succeed");
521}
522
523BOOST_AUTO_TEST_SUITE_END() // NonceValidation
524
525BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicySignedInterest
526BOOST_AUTO_TEST_SUITE_END() // Security
527
528} // namespace tests
529} // inline namespace v2
530} // namespace security
531} // namespace ndn