blob: 75d1f5ef7ffd971a4de0ccf55e03001418c391ce [file] [log] [blame]
Eric Newberry1caa6342020-08-23 19:29:08 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Davide Pesavento0c526032024-01-31 21:14:01 -05003 * Copyright (c) 2013-2024 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-simple-hierarchy.hpp"
26
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050027#include "tests/test-common.hpp"
Eric Newberry1caa6342020-08-23 19:29:08 -070028#include "tests/unit/security/validator-fixture.hpp"
29
Davide Pesavento49e1e872023-11-11 00:45:23 -050030#include <boost/mp11/list.hpp>
Eric Newberry1caa6342020-08-23 19:29:08 -070031
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040032namespace ndn::tests {
Eric Newberry1caa6342020-08-23 19:29:08 -070033
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040034using namespace ndn::security;
Eric Newberry1caa6342020-08-23 19:29:08 -070035
36BOOST_AUTO_TEST_SUITE(Security)
37
Davide Pesavento2acce252022-09-08 22:03:03 -040038struct SignedInterestDefaultOptions
Eric Newberry1caa6342020-08-23 19:29:08 -070039{
Davide Pesavento0c526032024-01-31 21:14:01 -050040 static auto
Eric Newberry1caa6342020-08-23 19:29:08 -070041 getOptions()
42 {
Davide Pesavento0c526032024-01-31 21:14:01 -050043 return ValidationPolicySignedInterest::Options{};
Eric Newberry1caa6342020-08-23 19:29:08 -070044 }
45};
46
Davide Pesavento0c526032024-01-31 21:14:01 -050047template<class ValidationOptions, class InnerPolicy>
Eric Newberry1caa6342020-08-23 19:29:08 -070048class SignedInterestPolicyWrapper : public ValidationPolicySignedInterest
49{
50public:
51 SignedInterestPolicyWrapper()
Davide Pesavento0c526032024-01-31 21:14:01 -050052 : ValidationPolicySignedInterest(make_unique<InnerPolicy>(), ValidationOptions::getOptions())
Eric Newberry1caa6342020-08-23 19:29:08 -070053 {
54 }
55};
56
Davide Pesavento0c526032024-01-31 21:14:01 -050057template<class ValidationOptions = SignedInterestDefaultOptions,
58 class InnerPolicy = ValidationPolicySimpleHierarchy>
Eric Newberry1caa6342020-08-23 19:29:08 -070059class ValidationPolicySignedInterestFixture
Davide Pesavento0c526032024-01-31 21:14:01 -050060 : public HierarchicalValidatorFixture<SignedInterestPolicyWrapper<ValidationOptions, InnerPolicy>>
Eric Newberry1caa6342020-08-23 19:29:08 -070061{
Davide Pesavento2acce252022-09-08 22:03:03 -040062protected:
Eric Newberry1caa6342020-08-23 19:29:08 -070063 Interest
Davide Pesavento0c526032024-01-31 21:14:01 -050064 makeSignedInterest(const Identity& id,
Eric Newberry1caa6342020-08-23 19:29:08 -070065 uint32_t signingFlags = InterestSigner::WantNonce | InterestSigner::WantTime)
66 {
Davide Pesavento0c526032024-01-31 21:14:01 -050067 Interest interest(Name(id.getName()).append("CMD"));
68 m_signer.makeSignedInterest(interest, signingByIdentity(id), signingFlags);
69 return interest;
Eric Newberry1caa6342020-08-23 19:29:08 -070070 }
71
Davide Pesavento2acce252022-09-08 22:03:03 -040072protected:
73 InterestSigner m_signer{this->m_keyChain};
Eric Newberry1caa6342020-08-23 19:29:08 -070074 static constexpr uint32_t WantAll = InterestSigner::WantNonce |
Davide Pesavento0c526032024-01-31 21:14:01 -050075 InterestSigner::WantTime |
76 InterestSigner::WantSeqNum;
Eric Newberry1caa6342020-08-23 19:29:08 -070077};
78
Davide Pesavento0c526032024-01-31 21:14:01 -050079BOOST_FIXTURE_TEST_SUITE(TestValidationPolicySignedInterest, ValidationPolicySignedInterestFixture<>)
Eric Newberry1caa6342020-08-23 19:29:08 -070080
Davide Pesavento2acce252022-09-08 22:03:03 -040081BOOST_AUTO_TEST_CASE(Basic)
Eric Newberry1caa6342020-08-23 19:29:08 -070082{
83 auto i1 = makeSignedInterest(identity, WantAll);
84 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
85 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -040086 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -070087
88 advanceClocks(5_ms);
89 auto i2 = makeSignedInterest(identity, WantAll);
90 VALIDATE_SUCCESS(i2, "Should succeed (timestamp and sequence number larger than previous)");
91
92 Interest i3(Name(identity.getName()).append("CMD"));
Eric Newberry1caa6342020-08-23 19:29:08 -070093 m_signer.makeSignedInterest(i3, signingWithSha256());
94 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Davide Pesavento2acce252022-09-08 22:03:03 -040095 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -070096}
97
98BOOST_AUTO_TEST_CASE(DataPassthrough)
99{
100 Data d1("/Security/ValidatorFixture/Sub1");
101 m_keyChain.sign(d1);
102 VALIDATE_SUCCESS(d1, "Should succeed (fallback on inner validation policy for data)");
103}
104
105BOOST_AUTO_TEST_CASE(InnerPolicyReject)
106{
107 auto i1 = makeSignedInterest(otherIdentity);
108 VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400109 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
Eric Newberry1caa6342020-08-23 19:29:08 -0700110}
111
Davide Pesavento2acce252022-09-08 22:03:03 -0400112template<ssize_t count>
113struct MaxRecordCount
Eric Newberry1caa6342020-08-23 19:29:08 -0700114{
Davide Pesavento0c526032024-01-31 21:14:01 -0500115 static auto
Eric Newberry1caa6342020-08-23 19:29:08 -0700116 getOptions()
117 {
118 ValidationPolicySignedInterest::Options options;
119 options.timestampGracePeriod = 15_s;
Davide Pesavento2acce252022-09-08 22:03:03 -0400120 options.maxRecordCount = count;
Eric Newberry1caa6342020-08-23 19:29:08 -0700121 return options;
122 }
123};
124
Davide Pesavento2acce252022-09-08 22:03:03 -0400125BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<3>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700126{
127 Identity id1 = addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
128 cache.insert(id1.getDefaultKey().getDefaultCertificate());
129 Identity id2 = addSubCertificate("/Security/ValidatorFixture/Sub2", identity);
130 cache.insert(id2.getDefaultKey().getDefaultCertificate());
131 Identity id3 = addSubCertificate("/Security/ValidatorFixture/Sub3", identity);
132 cache.insert(id3.getDefaultKey().getDefaultCertificate());
133 Identity id4 = addSubCertificate("/Security/ValidatorFixture/Sub4", identity);
134 cache.insert(id4.getDefaultKey().getDefaultCertificate());
135
136 auto i1 = makeSignedInterest(id2);
137 auto i2 = makeSignedInterest(id3);
138 auto i3 = makeSignedInterest(id4);
139 auto i00 = makeSignedInterest(id1); // signed at 0s
140 advanceClocks(1_s);
141 auto i01 = makeSignedInterest(id1); // signed at 1s
142 advanceClocks(1_s);
143 auto i02 = makeSignedInterest(id1); // signed at 2s
144
145 VALIDATE_SUCCESS(i00, "Should succeed");
146 rewindClockAfterValidation();
147
148 VALIDATE_SUCCESS(i02, "Should succeed");
149 rewindClockAfterValidation();
150
151 VALIDATE_SUCCESS(i1, "Should succeed");
152 rewindClockAfterValidation();
153
154 VALIDATE_SUCCESS(i2, "Should succeed");
155 rewindClockAfterValidation();
156
157 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
158 rewindClockAfterValidation();
159
160 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
161}
162
Davide Pesavento2acce252022-09-08 22:03:03 -0400163BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<-1>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700164{
165 std::vector<Identity> identities;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500166 for (size_t i = 0; i < 20; ++i) {
Eric Newberry1caa6342020-08-23 19:29:08 -0700167 Identity id = addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
168 cache.insert(id.getDefaultKey().getDefaultCertificate());
169 identities.push_back(id);
170 }
171
172 auto i1 = makeSignedInterest(identities.at(0)); // signed at 0s
173 advanceClocks(1_s);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500174 for (size_t i = 0; i < 20; ++i) {
Eric Newberry1caa6342020-08-23 19:29:08 -0700175 auto i2 = makeSignedInterest(identities.at(i)); // signed at +1s
Eric Newberry1caa6342020-08-23 19:29:08 -0700176 VALIDATE_SUCCESS(i2, "Should succeed");
177 rewindClockAfterValidation();
178 }
Davide Pesavento2acce252022-09-08 22:03:03 -0400179
Eric Newberry1caa6342020-08-23 19:29:08 -0700180 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400181 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700182}
183
Davide Pesavento2acce252022-09-08 22:03:03 -0400184BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<0>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700185{
186 auto i1 = makeSignedInterest(identity); // signed at 0s
187 advanceClocks(1_s);
188 auto i2 = makeSignedInterest(identity); // signed at +1s
189 VALIDATE_SUCCESS(i2, "Should succeed");
190 rewindClockAfterValidation();
191
192 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp reordering, as records aren't kept");
193}
194
Davide Pesavento0c526032024-01-31 21:14:01 -0500195struct DisabledTimestampValidation
196{
197 static auto
198 getOptions()
199 {
200 ValidationPolicySignedInterest::Options options;
201 options.shouldValidateTimestamps = false;
202 return options;
203 }
204};
205
206template<int secs>
207struct GracePeriodSeconds
208{
209 static auto
210 getOptions()
211 {
212 ValidationPolicySignedInterest::Options options;
213 options.timestampGracePeriod = time::seconds(secs);
214 return options;
215 }
216};
217
Eric Newberry1caa6342020-08-23 19:29:08 -0700218BOOST_AUTO_TEST_SUITE(TimestampValidation)
219
220BOOST_AUTO_TEST_CASE(MissingTimestamp)
221{
222 auto i1 = makeSignedInterest(identity, InterestSigner::WantSeqNum);
223 VALIDATE_FAILURE(i1, "Should fail (timestamp missing)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400224 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700225}
226
Davide Pesavento0c526032024-01-31 21:14:01 -0500227BOOST_FIXTURE_TEST_CASE(Disabled, ValidationPolicySignedInterestFixture<DisabledTimestampValidation>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700228{
229 auto i1 = makeSignedInterest(identity); // signed at 0ms
230 advanceClocks(100_ms);
231 VALIDATE_SUCCESS(i1, "Should succeed");
232
233 auto i2 = makeSignedInterest(identity); // signed at +100ms
234 // Set i2 to have same timestamp as i1
235 auto si2 = i2.getSignatureInfo();
236 si2->setTime(i2.getSignatureInfo()->getTime());
237 i2.setSignatureInfo(*si2);
238 VALIDATE_SUCCESS(i2, "Should succeed");
239}
240
Davide Pesavento2acce252022-09-08 22:03:03 -0400241BOOST_FIXTURE_TEST_CASE(TimestampTooOld, ValidationPolicySignedInterestFixture<GracePeriodSeconds<15>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700242{
243 auto i1 = makeSignedInterest(identity); // signed at 0s
244 advanceClocks(16_s); // verifying at +16s
245 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400246 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700247 rewindClockAfterValidation();
248
249 auto i2 = makeSignedInterest(identity); // signed at +16s
250 VALIDATE_SUCCESS(i2, "Should succeed");
251}
252
Davide Pesavento2acce252022-09-08 22:03:03 -0400253BOOST_FIXTURE_TEST_CASE(TimestampTooNew, ValidationPolicySignedInterestFixture<GracePeriodSeconds<15>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700254{
255 auto i1 = makeSignedInterest(identity); // signed at 0s
256 advanceClocks(1_s);
257 auto i2 = makeSignedInterest(identity); // signed at +1s
258 advanceClocks(1_s);
259 auto i3 = makeSignedInterest(identity); // signed at +2s
260
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500261 m_systemClock->advance(-18_s); // verifying at -16s
Eric Newberry1caa6342020-08-23 19:29:08 -0700262 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400263 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700264 rewindClockAfterValidation();
265
266 // SignedInterestValidator should not remember i1's timestamp
267 VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400268 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700269 rewindClockAfterValidation();
270
271 // SignedInterestValidator should not remember i2's timestamp, and should treat i3 as initial
272 advanceClocks(18_s); // verifying at +2s
273 VALIDATE_SUCCESS(i3, "Should succeed");
274}
275
276BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
277{
278 auto i1 = makeSignedInterest(identity); // signed at 0s
279 VALIDATE_SUCCESS(i1, "Should succeed");
280
281 auto i2 = makeSignedInterest(identity); // signed at 0s
282 auto si2 = i2.getSignatureInfo();
283 si2->setTime(i1.getSignatureInfo()->getTime());
284 i2.setSignatureInfo(*si2);
285 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400286 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700287
288 advanceClocks(2_s);
289 auto i3 = makeSignedInterest(identity); // signed at +2s
290 VALIDATE_SUCCESS(i3, "Should succeed");
291}
292
293BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
294{
295 auto i2 = makeSignedInterest(identity); // signed at 0ms
296 advanceClocks(200_ms);
297 auto i3 = makeSignedInterest(identity); // signed at +200ms
298 advanceClocks(900_ms);
299 auto i1 = makeSignedInterest(identity); // signed at +1100ms
300 advanceClocks(300_ms);
301 auto i4 = makeSignedInterest(identity); // signed at +1400ms
302
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500303 m_systemClock->advance(-300_ms); // verifying at +1100ms
Eric Newberry1caa6342020-08-23 19:29:08 -0700304 VALIDATE_SUCCESS(i1, "Should succeed");
305 rewindClockAfterValidation();
306
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500307 m_systemClock->advance(-1100_ms); // verifying at 0ms
Eric Newberry1caa6342020-08-23 19:29:08 -0700308 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400309 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700310 rewindClockAfterValidation();
311
312 // SignedInterestValidator should not remember i2's timestamp
313 advanceClocks(200_ms); // verifying at +200ms
314 VALIDATE_FAILURE(i3, "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 advanceClocks(1200_ms); // verifying at 1400ms
319 VALIDATE_SUCCESS(i4, "Should succeed");
320}
321
Davide Pesavento49e1e872023-11-11 00:45:23 -0500322using NonPositiveGracePeriods = boost::mp11::mp_list<GracePeriodSeconds<0>, GracePeriodSeconds<-1>>;
Eric Newberry1caa6342020-08-23 19:29:08 -0700323
Davide Pesavento2acce252022-09-08 22:03:03 -0400324BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, NonPositiveGracePeriods,
Eric Newberry1caa6342020-08-23 19:29:08 -0700325 ValidationPolicySignedInterestFixture<GracePeriod>)
326{
327 auto i1 = this->makeSignedInterest(this->identity); // signed at 0ms
328 auto i2 = this->makeSignedInterest(this->subIdentity); // signed at 0ms
329 // ensure timestamps are exactly 0ms
330 for (auto interest : {&i1, &i2}) {
331 auto si = interest->getSignatureInfo();
332 si->setTime(time::system_clock::now());
333 interest->setSignatureInfo(*si);
334 }
335
336 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
337 this->rewindClockAfterValidation();
338
339 this->advanceClocks(1_ms);
340 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
Davide Pesavento2acce252022-09-08 22:03:03 -0400341 BOOST_TEST(this->lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700342}
343
344BOOST_AUTO_TEST_SUITE_END() // TimestampValidation
345
Davide Pesavento0c526032024-01-31 21:14:01 -0500346struct EnabledSeqNumValidation
347{
348 static auto
349 getOptions()
350 {
351 ValidationPolicySignedInterest::Options options;
352 options.shouldValidateSeqNums = true;
353 return options;
354 }
355};
356
Eric Newberry1caa6342020-08-23 19:29:08 -0700357BOOST_AUTO_TEST_SUITE(SeqNumValidation)
358
359// By default, sequence number validation is disabled
360BOOST_AUTO_TEST_CASE(Disabled)
361{
362 auto i1 = makeSignedInterest(identity, WantAll); // signed at 0ms
363 VALIDATE_SUCCESS(i1, "Should succeed");
364
365 auto i2 = makeSignedInterest(identity, WantAll); // signed at +100ms
366 // Set i2 to have same seq num as i1
367 auto si2 = i2.getSignatureInfo();
368 si2->setSeqNum(i2.getSignatureInfo()->getSeqNum());
369 i2.setSignatureInfo(*si2);
370 VALIDATE_SUCCESS(i2, "Should succeed");
371}
372
Davide Pesavento0c526032024-01-31 21:14:01 -0500373BOOST_FIXTURE_TEST_CASE(MissingSeqNum, ValidationPolicySignedInterestFixture<EnabledSeqNumValidation>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700374{
375 auto i1 = makeSignedInterest(identity, InterestSigner::WantTime);
376 VALIDATE_FAILURE(i1, "Should fail (sequence number missing");
Davide Pesavento2acce252022-09-08 22:03:03 -0400377 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700378}
379
Davide Pesavento0c526032024-01-31 21:14:01 -0500380BOOST_FIXTURE_TEST_CASE(SeqNumReorder, ValidationPolicySignedInterestFixture<EnabledSeqNumValidation>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700381{
382 auto i1 = makeSignedInterest(identity, WantAll); // seq num is i
383 VALIDATE_SUCCESS(i1, "Should succeed");
384
385 auto i2 = makeSignedInterest(identity, WantAll); // seq num is i+1
386 auto si2 = i2.getSignatureInfo();
387 si2->setSeqNum(i1.getSignatureInfo()->getSeqNum());
388 i2.setSignatureInfo(*si2);
389 VALIDATE_FAILURE(i2, "Should fail (sequence number reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400390 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700391
392 auto i3 = makeSignedInterest(identity, WantAll); // seq num is i+2
393 VALIDATE_SUCCESS(i3, "Should succeed");
394}
395
396BOOST_AUTO_TEST_SUITE_END() // SeqNumValidation
397
Davide Pesavento0c526032024-01-31 21:14:01 -0500398struct DisabledNonceValidation
399{
400 static auto
401 getOptions()
402 {
403 ValidationPolicySignedInterest::Options options;
404 options.shouldValidateNonces = false;
405 return options;
406 }
407};
408
409template<ssize_t count>
410struct MaxNonceRecordCount
411{
412 static auto
413 getOptions()
414 {
415 ValidationPolicySignedInterest::Options options;
416 options.shouldValidateTimestamps = false;
417 options.shouldValidateSeqNums = false;
418 options.maxNonceRecordCount = count;
419 return options;
420 }
421};
422
Eric Newberry1caa6342020-08-23 19:29:08 -0700423BOOST_AUTO_TEST_SUITE(NonceValidation)
424
425BOOST_AUTO_TEST_CASE(MissingNonce)
426{
427 auto i1 = makeSignedInterest(identity, InterestSigner::WantTime); // Specifically exclude nonce
428 VALIDATE_FAILURE(i1, "Should fail (nonce missing)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400429 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700430}
431
432BOOST_AUTO_TEST_CASE(DuplicateNonce)
433{
434 auto i1 = makeSignedInterest(identity, WantAll);
435 VALIDATE_SUCCESS(i1, "Should succeed");
436
437 auto i2 = makeSignedInterest(identity, WantAll);
438 auto si2 = i2.getSignatureInfo();
439 si2->setNonce(i1.getSignatureInfo()->getNonce());
440 i2.setSignatureInfo(*si2);
441 VALIDATE_FAILURE(i2, "Should fail (duplicate nonce)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400442 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700443
444 auto i3 = makeSignedInterest(identity, WantAll);
445 // On the off chance that the generated nonce is identical to i1
446 while (i3.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce()) {
447 i3 = makeSignedInterest(identity, WantAll);
448 }
449 VALIDATE_SUCCESS(i3, "Should succeed");
450}
451
Davide Pesavento0c526032024-01-31 21:14:01 -0500452BOOST_FIXTURE_TEST_CASE(Disabled, ValidationPolicySignedInterestFixture<DisabledNonceValidation>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700453{
454 auto i1 = makeSignedInterest(identity, WantAll ^ InterestSigner::WantNonce);
455 VALIDATE_SUCCESS(i1, "Should succeed");
456
457 // Ensure still works when a nonce is present
458 auto i2 = makeSignedInterest(identity, WantAll);
459 VALIDATE_SUCCESS(i2, "Should succeed");
460
461 // Ensure a duplicate still succeeds
462 auto i3 = makeSignedInterest(identity, WantAll);
463 auto si3 = i3.getSignatureInfo();
464 si3->setNonce(i2.getSignatureInfo()->getNonce());
465 i3.setSignatureInfo(*si3);
466 m_keyChain.sign(i3, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
467 .setSignatureInfo(*si3));
468 VALIDATE_SUCCESS(i3, "Should succeed");
469}
470
Davide Pesavento0c526032024-01-31 21:14:01 -0500471BOOST_FIXTURE_TEST_CASE(NonceRecordLimit, ValidationPolicySignedInterestFixture<MaxNonceRecordCount<2>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700472{
473 auto i1 = makeSignedInterest(identity, WantAll);
474 VALIDATE_SUCCESS(i1, "Should succeed");
475
476 auto i2 = makeSignedInterest(identity, WantAll);
477 // On the off chance that the generated nonce is identical to i1
478 while (i2.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce()) {
479 i2 = makeSignedInterest(identity, WantAll);
480 }
481 VALIDATE_SUCCESS(i2, "Should succeed");
482
483 auto i3 = makeSignedInterest(identity, WantAll);
484 auto si3 = i3.getSignatureInfo();
485 si3->setNonce(i1.getSignatureInfo()->getNonce());
486 i3.setSignatureInfo(*si3);
487 m_keyChain.sign(i3, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
488 .setSignatureInfo(*si3));
489 VALIDATE_FAILURE(i3, "Should fail (duplicate nonce)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400490 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700491
492 // Pop i1's nonce off the list
493 auto i4 = makeSignedInterest(identity, WantAll);
494 // On the off chance that the generated nonce is identical to i1 or i2
495 while (i4.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce() ||
496 i4.getSignatureInfo()->getNonce() == i2.getSignatureInfo()->getNonce()) {
497 i4 = makeSignedInterest(identity, WantAll);
498 }
499 VALIDATE_SUCCESS(i4, "Should succeed");
500
501 // Now i3 should succeed because i1's nonce has been popped off the list
502 auto i5 = makeSignedInterest(identity, WantAll);
503 auto si5 = i5.getSignatureInfo();
504 si5->setNonce(i1.getSignatureInfo()->getNonce());
505 i5.setSignatureInfo(*si5);
506 m_keyChain.sign(i5, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
507 .setSignatureInfo(*si5));
508 VALIDATE_SUCCESS(i5, "Should succeed");
509}
510
511BOOST_AUTO_TEST_SUITE_END() // NonceValidation
512
513BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicySignedInterest
514BOOST_AUTO_TEST_SUITE_END() // Security
515
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400516} // namespace ndn::tests