blob: 2cd91a7ba08bf5919da8dd2de767e76aa02a4035 [file] [log] [blame]
Eric Newberry1caa6342020-08-23 19:29:08 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Davide Pesavento47ce2ee2023-05-09 01:33:33 -04003 * Copyright (c) 2013-2023 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
Davide Pesavento49e1e872023-11-11 00:45:23 -050031#include <boost/mp11/list.hpp>
Eric Newberry1caa6342020-08-23 19:29:08 -070032
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040033namespace ndn::tests {
Eric Newberry1caa6342020-08-23 19:29:08 -070034
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040035using namespace ndn::security;
Eric Newberry1caa6342020-08-23 19:29:08 -070036
37BOOST_AUTO_TEST_SUITE(Security)
38
Davide Pesavento2acce252022-09-08 22:03:03 -040039struct SignedInterestDefaultOptions
Eric Newberry1caa6342020-08-23 19:29:08 -070040{
Eric Newberry1caa6342020-08-23 19:29:08 -070041 static ValidationPolicySignedInterest::Options
42 getOptions()
43 {
44 return {};
45 }
46};
47
48template<class T, class InnerPolicy>
49class SignedInterestPolicyWrapper : public ValidationPolicySignedInterest
50{
51public:
52 SignedInterestPolicyWrapper()
53 : ValidationPolicySignedInterest(make_unique<InnerPolicy>(), T::getOptions())
54 {
55 }
56};
57
58template<class T, class InnerPolicy = ValidationPolicySimpleHierarchy>
59class ValidationPolicySignedInterestFixture
60 : public HierarchicalValidatorFixture<SignedInterestPolicyWrapper<T, InnerPolicy>>
61{
Davide Pesavento2acce252022-09-08 22:03:03 -040062protected:
Eric Newberry1caa6342020-08-23 19:29:08 -070063 Interest
64 makeSignedInterest(const Identity& identity,
65 uint32_t signingFlags = InterestSigner::WantNonce | InterestSigner::WantTime)
66 {
67 Interest i(Name(identity.getName()).append("CMD"));
Eric Newberry1caa6342020-08-23 19:29:08 -070068 m_signer.makeSignedInterest(i, signingByIdentity(identity), signingFlags);
69 return i;
70 }
71
Davide Pesavento2acce252022-09-08 22:03:03 -040072protected:
73 InterestSigner m_signer{this->m_keyChain};
Eric Newberry1caa6342020-08-23 19:29:08 -070074
75 static constexpr uint32_t WantAll = InterestSigner::WantNonce |
76 InterestSigner::WantTime |
77 InterestSigner::WantSeqNum;
78};
79
80BOOST_FIXTURE_TEST_SUITE(TestValidationPolicySignedInterest,
81 ValidationPolicySignedInterestFixture<SignedInterestDefaultOptions>)
82
Davide Pesavento2acce252022-09-08 22:03:03 -040083BOOST_AUTO_TEST_CASE(Basic)
Eric Newberry1caa6342020-08-23 19:29:08 -070084{
85 auto i1 = makeSignedInterest(identity, WantAll);
86 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
87 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -040088 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -070089
90 advanceClocks(5_ms);
91 auto i2 = makeSignedInterest(identity, WantAll);
92 VALIDATE_SUCCESS(i2, "Should succeed (timestamp and sequence number larger than previous)");
93
94 Interest i3(Name(identity.getName()).append("CMD"));
Eric Newberry1caa6342020-08-23 19:29:08 -070095 m_signer.makeSignedInterest(i3, signingWithSha256());
96 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Davide Pesavento2acce252022-09-08 22:03:03 -040097 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -070098}
99
100BOOST_AUTO_TEST_CASE(DataPassthrough)
101{
102 Data d1("/Security/ValidatorFixture/Sub1");
103 m_keyChain.sign(d1);
104 VALIDATE_SUCCESS(d1, "Should succeed (fallback on inner validation policy for data)");
105}
106
107BOOST_AUTO_TEST_CASE(InnerPolicyReject)
108{
109 auto i1 = makeSignedInterest(otherIdentity);
110 VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400111 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
Eric Newberry1caa6342020-08-23 19:29:08 -0700112}
113
Davide Pesavento2acce252022-09-08 22:03:03 -0400114template<ssize_t count>
115struct MaxRecordCount
Eric Newberry1caa6342020-08-23 19:29:08 -0700116{
Eric Newberry1caa6342020-08-23 19:29:08 -0700117 static ValidationPolicySignedInterest::Options
118 getOptions()
119 {
120 ValidationPolicySignedInterest::Options options;
121 options.timestampGracePeriod = 15_s;
Davide Pesavento2acce252022-09-08 22:03:03 -0400122 options.maxRecordCount = count;
Eric Newberry1caa6342020-08-23 19:29:08 -0700123 return options;
124 }
125};
126
Davide Pesavento2acce252022-09-08 22:03:03 -0400127BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<3>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700128{
129 Identity id1 = addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
130 cache.insert(id1.getDefaultKey().getDefaultCertificate());
131 Identity id2 = addSubCertificate("/Security/ValidatorFixture/Sub2", identity);
132 cache.insert(id2.getDefaultKey().getDefaultCertificate());
133 Identity id3 = addSubCertificate("/Security/ValidatorFixture/Sub3", identity);
134 cache.insert(id3.getDefaultKey().getDefaultCertificate());
135 Identity id4 = addSubCertificate("/Security/ValidatorFixture/Sub4", identity);
136 cache.insert(id4.getDefaultKey().getDefaultCertificate());
137
138 auto i1 = makeSignedInterest(id2);
139 auto i2 = makeSignedInterest(id3);
140 auto i3 = makeSignedInterest(id4);
141 auto i00 = makeSignedInterest(id1); // signed at 0s
142 advanceClocks(1_s);
143 auto i01 = makeSignedInterest(id1); // signed at 1s
144 advanceClocks(1_s);
145 auto i02 = makeSignedInterest(id1); // signed at 2s
146
147 VALIDATE_SUCCESS(i00, "Should succeed");
148 rewindClockAfterValidation();
149
150 VALIDATE_SUCCESS(i02, "Should succeed");
151 rewindClockAfterValidation();
152
153 VALIDATE_SUCCESS(i1, "Should succeed");
154 rewindClockAfterValidation();
155
156 VALIDATE_SUCCESS(i2, "Should succeed");
157 rewindClockAfterValidation();
158
159 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
160 rewindClockAfterValidation();
161
162 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
163}
164
Davide Pesavento2acce252022-09-08 22:03:03 -0400165BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<-1>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700166{
167 std::vector<Identity> identities;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500168 for (size_t i = 0; i < 20; ++i) {
Eric Newberry1caa6342020-08-23 19:29:08 -0700169 Identity id = addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
170 cache.insert(id.getDefaultKey().getDefaultCertificate());
171 identities.push_back(id);
172 }
173
174 auto i1 = makeSignedInterest(identities.at(0)); // signed at 0s
175 advanceClocks(1_s);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500176 for (size_t i = 0; i < 20; ++i) {
Eric Newberry1caa6342020-08-23 19:29:08 -0700177 auto i2 = makeSignedInterest(identities.at(i)); // signed at +1s
Eric Newberry1caa6342020-08-23 19:29:08 -0700178 VALIDATE_SUCCESS(i2, "Should succeed");
179 rewindClockAfterValidation();
180 }
Davide Pesavento2acce252022-09-08 22:03:03 -0400181
Eric Newberry1caa6342020-08-23 19:29:08 -0700182 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400183 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700184}
185
Davide Pesavento2acce252022-09-08 22:03:03 -0400186BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicySignedInterestFixture<MaxRecordCount<0>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700187{
188 auto i1 = makeSignedInterest(identity); // signed at 0s
189 advanceClocks(1_s);
190 auto i2 = makeSignedInterest(identity); // signed at +1s
191 VALIDATE_SUCCESS(i2, "Should succeed");
192 rewindClockAfterValidation();
193
194 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp reordering, as records aren't kept");
195}
196
197BOOST_AUTO_TEST_SUITE(TimestampValidation)
198
199BOOST_AUTO_TEST_CASE(MissingTimestamp)
200{
201 auto i1 = makeSignedInterest(identity, InterestSigner::WantSeqNum);
202 VALIDATE_FAILURE(i1, "Should fail (timestamp missing)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400203 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700204}
205
Davide Pesavento2acce252022-09-08 22:03:03 -0400206struct DisabledTimestampValidationOptions
Eric Newberry1caa6342020-08-23 19:29:08 -0700207{
Eric Newberry1caa6342020-08-23 19:29:08 -0700208 static ValidationPolicySignedInterest::Options
209 getOptions()
210 {
211 ValidationPolicySignedInterest::Options options;
212 options.shouldValidateTimestamps = false;
213 return options;
214 }
215};
216
217BOOST_FIXTURE_TEST_CASE(Disabled,
218 ValidationPolicySignedInterestFixture<DisabledTimestampValidationOptions>)
219{
220 auto i1 = makeSignedInterest(identity); // signed at 0ms
221 advanceClocks(100_ms);
222 VALIDATE_SUCCESS(i1, "Should succeed");
223
224 auto i2 = makeSignedInterest(identity); // signed at +100ms
225 // Set i2 to have same timestamp as i1
226 auto si2 = i2.getSignatureInfo();
227 si2->setTime(i2.getSignatureInfo()->getTime());
228 i2.setSignatureInfo(*si2);
229 VALIDATE_SUCCESS(i2, "Should succeed");
230}
231
Davide Pesavento2acce252022-09-08 22:03:03 -0400232template<int secs>
233struct GracePeriodSeconds
Eric Newberry1caa6342020-08-23 19:29:08 -0700234{
Eric Newberry1caa6342020-08-23 19:29:08 -0700235 static ValidationPolicySignedInterest::Options
236 getOptions()
237 {
238 ValidationPolicySignedInterest::Options options;
Davide Pesavento2acce252022-09-08 22:03:03 -0400239 options.timestampGracePeriod = time::seconds(secs);
Eric Newberry1caa6342020-08-23 19:29:08 -0700240 return options;
241 }
242};
243
Davide Pesavento2acce252022-09-08 22:03:03 -0400244BOOST_FIXTURE_TEST_CASE(TimestampTooOld, ValidationPolicySignedInterestFixture<GracePeriodSeconds<15>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700245{
246 auto i1 = makeSignedInterest(identity); // signed at 0s
247 advanceClocks(16_s); // verifying at +16s
248 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400249 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700250 rewindClockAfterValidation();
251
252 auto i2 = makeSignedInterest(identity); // signed at +16s
253 VALIDATE_SUCCESS(i2, "Should succeed");
254}
255
Davide Pesavento2acce252022-09-08 22:03:03 -0400256BOOST_FIXTURE_TEST_CASE(TimestampTooNew, ValidationPolicySignedInterestFixture<GracePeriodSeconds<15>>)
Eric Newberry1caa6342020-08-23 19:29:08 -0700257{
258 auto i1 = makeSignedInterest(identity); // signed at 0s
259 advanceClocks(1_s);
260 auto i2 = makeSignedInterest(identity); // signed at +1s
261 advanceClocks(1_s);
262 auto i3 = makeSignedInterest(identity); // signed at +2s
263
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500264 m_systemClock->advance(-18_s); // verifying at -16s
Eric Newberry1caa6342020-08-23 19:29:08 -0700265 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400266 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700267 rewindClockAfterValidation();
268
269 // SignedInterestValidator should not remember i1's timestamp
270 VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400271 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700272 rewindClockAfterValidation();
273
274 // SignedInterestValidator should not remember i2's timestamp, and should treat i3 as initial
275 advanceClocks(18_s); // verifying at +2s
276 VALIDATE_SUCCESS(i3, "Should succeed");
277}
278
279BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
280{
281 auto i1 = makeSignedInterest(identity); // signed at 0s
282 VALIDATE_SUCCESS(i1, "Should succeed");
283
284 auto i2 = makeSignedInterest(identity); // signed at 0s
285 auto si2 = i2.getSignatureInfo();
286 si2->setTime(i1.getSignatureInfo()->getTime());
287 i2.setSignatureInfo(*si2);
288 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400289 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700290
291 advanceClocks(2_s);
292 auto i3 = makeSignedInterest(identity); // signed at +2s
293 VALIDATE_SUCCESS(i3, "Should succeed");
294}
295
296BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
297{
298 auto i2 = makeSignedInterest(identity); // signed at 0ms
299 advanceClocks(200_ms);
300 auto i3 = makeSignedInterest(identity); // signed at +200ms
301 advanceClocks(900_ms);
302 auto i1 = makeSignedInterest(identity); // signed at +1100ms
303 advanceClocks(300_ms);
304 auto i4 = makeSignedInterest(identity); // signed at +1400ms
305
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500306 m_systemClock->advance(-300_ms); // verifying at +1100ms
Eric Newberry1caa6342020-08-23 19:29:08 -0700307 VALIDATE_SUCCESS(i1, "Should succeed");
308 rewindClockAfterValidation();
309
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500310 m_systemClock->advance(-1100_ms); // verifying at 0ms
Eric Newberry1caa6342020-08-23 19:29:08 -0700311 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400312 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700313 rewindClockAfterValidation();
314
315 // SignedInterestValidator should not remember i2's timestamp
316 advanceClocks(200_ms); // verifying at +200ms
317 VALIDATE_FAILURE(i3, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400318 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700319 rewindClockAfterValidation();
320
321 advanceClocks(1200_ms); // verifying at 1400ms
322 VALIDATE_SUCCESS(i4, "Should succeed");
323}
324
Davide Pesavento49e1e872023-11-11 00:45:23 -0500325using NonPositiveGracePeriods = boost::mp11::mp_list<GracePeriodSeconds<0>, GracePeriodSeconds<-1>>;
Eric Newberry1caa6342020-08-23 19:29:08 -0700326
Davide Pesavento2acce252022-09-08 22:03:03 -0400327BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, NonPositiveGracePeriods,
Eric Newberry1caa6342020-08-23 19:29:08 -0700328 ValidationPolicySignedInterestFixture<GracePeriod>)
329{
330 auto i1 = this->makeSignedInterest(this->identity); // signed at 0ms
331 auto i2 = this->makeSignedInterest(this->subIdentity); // signed at 0ms
332 // ensure timestamps are exactly 0ms
333 for (auto interest : {&i1, &i2}) {
334 auto si = interest->getSignatureInfo();
335 si->setTime(time::system_clock::now());
336 interest->setSignatureInfo(*si);
337 }
338
339 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
340 this->rewindClockAfterValidation();
341
342 this->advanceClocks(1_ms);
343 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
Davide Pesavento2acce252022-09-08 22:03:03 -0400344 BOOST_TEST(this->lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700345}
346
347BOOST_AUTO_TEST_SUITE_END() // TimestampValidation
348
349BOOST_AUTO_TEST_SUITE(SeqNumValidation)
350
351// By default, sequence number validation is disabled
352BOOST_AUTO_TEST_CASE(Disabled)
353{
354 auto i1 = makeSignedInterest(identity, WantAll); // signed at 0ms
355 VALIDATE_SUCCESS(i1, "Should succeed");
356
357 auto i2 = makeSignedInterest(identity, WantAll); // signed at +100ms
358 // Set i2 to have same seq num as i1
359 auto si2 = i2.getSignatureInfo();
360 si2->setSeqNum(i2.getSignatureInfo()->getSeqNum());
361 i2.setSignatureInfo(*si2);
362 VALIDATE_SUCCESS(i2, "Should succeed");
363}
364
Davide Pesavento2acce252022-09-08 22:03:03 -0400365struct SeqNumValidationOptions
Eric Newberry1caa6342020-08-23 19:29:08 -0700366{
Eric Newberry1caa6342020-08-23 19:29:08 -0700367 static ValidationPolicySignedInterest::Options
368 getOptions()
369 {
370 ValidationPolicySignedInterest::Options options;
371 options.shouldValidateSeqNums = true;
372 return options;
373 }
374};
375
376BOOST_FIXTURE_TEST_CASE(MissingSeqNum,
377 ValidationPolicySignedInterestFixture<SeqNumValidationOptions>)
378{
379 auto i1 = makeSignedInterest(identity, InterestSigner::WantTime);
380 VALIDATE_FAILURE(i1, "Should fail (sequence number missing");
Davide Pesavento2acce252022-09-08 22:03:03 -0400381 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700382}
383
384BOOST_FIXTURE_TEST_CASE(SeqNumReorder,
385 ValidationPolicySignedInterestFixture<SeqNumValidationOptions>)
386{
387 auto i1 = makeSignedInterest(identity, WantAll); // seq num is i
388 VALIDATE_SUCCESS(i1, "Should succeed");
389
390 auto i2 = makeSignedInterest(identity, WantAll); // seq num is i+1
391 auto si2 = i2.getSignatureInfo();
392 si2->setSeqNum(i1.getSignatureInfo()->getSeqNum());
393 i2.setSignatureInfo(*si2);
394 VALIDATE_FAILURE(i2, "Should fail (sequence number reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400395 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700396
397 auto i3 = makeSignedInterest(identity, WantAll); // seq num is i+2
398 VALIDATE_SUCCESS(i3, "Should succeed");
399}
400
401BOOST_AUTO_TEST_SUITE_END() // SeqNumValidation
402
403BOOST_AUTO_TEST_SUITE(NonceValidation)
404
405BOOST_AUTO_TEST_CASE(MissingNonce)
406{
407 auto i1 = makeSignedInterest(identity, InterestSigner::WantTime); // Specifically exclude nonce
408 VALIDATE_FAILURE(i1, "Should fail (nonce missing)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400409 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700410}
411
412BOOST_AUTO_TEST_CASE(DuplicateNonce)
413{
414 auto i1 = makeSignedInterest(identity, WantAll);
415 VALIDATE_SUCCESS(i1, "Should succeed");
416
417 auto i2 = makeSignedInterest(identity, WantAll);
418 auto si2 = i2.getSignatureInfo();
419 si2->setNonce(i1.getSignatureInfo()->getNonce());
420 i2.setSignatureInfo(*si2);
421 VALIDATE_FAILURE(i2, "Should fail (duplicate nonce)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400422 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700423
424 auto i3 = makeSignedInterest(identity, WantAll);
425 // On the off chance that the generated nonce is identical to i1
426 while (i3.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce()) {
427 i3 = makeSignedInterest(identity, WantAll);
428 }
429 VALIDATE_SUCCESS(i3, "Should succeed");
430}
431
Davide Pesavento2acce252022-09-08 22:03:03 -0400432struct DisabledNonceValidationOptions
Eric Newberry1caa6342020-08-23 19:29:08 -0700433{
Eric Newberry1caa6342020-08-23 19:29:08 -0700434 static ValidationPolicySignedInterest::Options
435 getOptions()
436 {
437 ValidationPolicySignedInterest::Options options;
438 options.shouldValidateNonces = false;
439 return options;
440 }
441};
442
443BOOST_FIXTURE_TEST_CASE(Disabled,
444 ValidationPolicySignedInterestFixture<DisabledNonceValidationOptions>)
445{
446 auto i1 = makeSignedInterest(identity, WantAll ^ InterestSigner::WantNonce);
447 VALIDATE_SUCCESS(i1, "Should succeed");
448
449 // Ensure still works when a nonce is present
450 auto i2 = makeSignedInterest(identity, WantAll);
451 VALIDATE_SUCCESS(i2, "Should succeed");
452
453 // Ensure a duplicate still succeeds
454 auto i3 = makeSignedInterest(identity, WantAll);
455 auto si3 = i3.getSignatureInfo();
456 si3->setNonce(i2.getSignatureInfo()->getNonce());
457 i3.setSignatureInfo(*si3);
458 m_keyChain.sign(i3, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
459 .setSignatureInfo(*si3));
460 VALIDATE_SUCCESS(i3, "Should succeed");
461}
462
Davide Pesavento2acce252022-09-08 22:03:03 -0400463struct NonceLimit2Options
Eric Newberry1caa6342020-08-23 19:29:08 -0700464{
Eric Newberry1caa6342020-08-23 19:29:08 -0700465 static ValidationPolicySignedInterest::Options
466 getOptions()
467 {
468 ValidationPolicySignedInterest::Options options;
469 options.shouldValidateTimestamps = false;
470 options.shouldValidateSeqNums = false;
471 options.maxNonceRecordCount = 2;
472 return options;
473 }
474};
475
476BOOST_FIXTURE_TEST_CASE(NonceRecordLimit,
477 ValidationPolicySignedInterestFixture<NonceLimit2Options>)
478{
479 auto i1 = makeSignedInterest(identity, WantAll);
480 VALIDATE_SUCCESS(i1, "Should succeed");
481
482 auto i2 = makeSignedInterest(identity, WantAll);
483 // On the off chance that the generated nonce is identical to i1
484 while (i2.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce()) {
485 i2 = makeSignedInterest(identity, WantAll);
486 }
487 VALIDATE_SUCCESS(i2, "Should succeed");
488
489 auto i3 = makeSignedInterest(identity, WantAll);
490 auto si3 = i3.getSignatureInfo();
491 si3->setNonce(i1.getSignatureInfo()->getNonce());
492 i3.setSignatureInfo(*si3);
493 m_keyChain.sign(i3, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
494 .setSignatureInfo(*si3));
495 VALIDATE_FAILURE(i3, "Should fail (duplicate nonce)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400496 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry1caa6342020-08-23 19:29:08 -0700497
498 // Pop i1's nonce off the list
499 auto i4 = makeSignedInterest(identity, WantAll);
500 // On the off chance that the generated nonce is identical to i1 or i2
501 while (i4.getSignatureInfo()->getNonce() == i1.getSignatureInfo()->getNonce() ||
502 i4.getSignatureInfo()->getNonce() == i2.getSignatureInfo()->getNonce()) {
503 i4 = makeSignedInterest(identity, WantAll);
504 }
505 VALIDATE_SUCCESS(i4, "Should succeed");
506
507 // Now i3 should succeed because i1's nonce has been popped off the list
508 auto i5 = makeSignedInterest(identity, WantAll);
509 auto si5 = i5.getSignatureInfo();
510 si5->setNonce(i1.getSignatureInfo()->getNonce());
511 i5.setSignatureInfo(*si5);
512 m_keyChain.sign(i5, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V03)
513 .setSignatureInfo(*si5));
514 VALIDATE_SUCCESS(i5, "Should succeed");
515}
516
517BOOST_AUTO_TEST_SUITE_END() // NonceValidation
518
519BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicySignedInterest
520BOOST_AUTO_TEST_SUITE_END() // Security
521
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400522} // namespace ndn::tests