blob: 9d04b6dbd481c2296afc9e7c5e3452e6c7b3de41 [file] [log] [blame]
Zhiyi Zhangf4bb5c72015-08-19 19:02:51 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento0f830802018-01-16 23:58:58 -05002/*
3 * Copyright (c) 2013-2018 Regents of the University of California.
Zhiyi Zhangf4bb5c72015-08-19 19:02:51 -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 * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
22 */
23
Davide Pesavento7e780642018-11-24 15:51:34 -050024#include "ndn-cxx/security/v2/certificate.hpp"
Zhiyi Zhangf4bb5c72015-08-19 19:02:51 -070025
Davide Pesavento7e780642018-11-24 15:51:34 -050026#include "tests/boost-test.hpp"
27#include "tests/unit/unit-test-time-fixture.hpp"
Davide Pesavento74daf742018-11-23 18:14:13 -050028
Zhiyi Zhangf4bb5c72015-08-19 19:02:51 -070029#include <boost/lexical_cast.hpp>
30
31namespace ndn {
32namespace security {
33namespace v2 {
34namespace tests {
35
36using namespace ndn::tests;
37
38BOOST_AUTO_TEST_SUITE(Security)
39BOOST_AUTO_TEST_SUITE(V2)
40BOOST_FIXTURE_TEST_SUITE(TestCertificate, UnitTestTimeFixture)
41
42const uint8_t PUBLIC_KEY[] = {
43 0x30, 0x81, 0x9d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
44 0x01, 0x05, 0x00, 0x03, 0x81, 0x8b, 0x00, 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e,
45 0x06, 0x3e, 0x47, 0x85, 0xb2, 0x34, 0x37, 0xaa, 0x85, 0x47, 0xac, 0x03, 0x24, 0x83, 0xb5,
46 0x9c, 0xa8, 0x05, 0x3a, 0x24, 0x1e, 0xeb, 0x89, 0x01, 0xbb, 0xe9, 0x9b, 0xb2, 0xc3, 0x22,
47 0xac, 0x68, 0xe3, 0xf0, 0x6c, 0x02, 0xce, 0x68, 0xa6, 0xc4, 0xd0, 0xa7, 0x06, 0x90, 0x9c,
48 0xaa, 0x1b, 0x08, 0x1d, 0x8b, 0x43, 0x9a, 0x33, 0x67, 0x44, 0x6d, 0x21, 0xa3, 0x1b, 0x88,
49 0x9a, 0x97, 0x5e, 0x59, 0xc4, 0x15, 0x0b, 0xd9, 0x2c, 0xbd, 0x51, 0x07, 0x61, 0x82, 0xad,
50 0xc1, 0xb8, 0xd7, 0xbf, 0x9b, 0xcf, 0x7d, 0x24, 0xc2, 0x63, 0xf3, 0x97, 0x17, 0xeb, 0xfe,
51 0x62, 0x25, 0xba, 0x5b, 0x4d, 0x8a, 0xc2, 0x7a, 0xbd, 0x43, 0x8a, 0x8f, 0xb8, 0xf2, 0xf1,
52 0xc5, 0x6a, 0x30, 0xd3, 0x50, 0x8c, 0xc8, 0x9a, 0xdf, 0xef, 0xed, 0x35, 0xe7, 0x7a, 0x62,
53 0xea, 0x76, 0x7c, 0xbb, 0x08, 0x26, 0xc7, 0x02, 0x01, 0x11
54};
55
56const uint8_t SIG_INFO[] = {
57 0x16, 0x55, 0x1B, 0x01, 0x01, 0x1C, 0x26, 0x07, 0x24, 0x08, 0x03, 0x6E, 0x64, 0x6E, 0x08, 0x05,
58 0x73, 0x69, 0x74, 0x65, 0x31, 0x08, 0x11, 0x6B, 0x73, 0x6B, 0x2D, 0x32, 0x35, 0x31, 0x36, 0x34,
59 0x32, 0x35, 0x33, 0x37, 0x37, 0x30, 0x39, 0x34, 0x08, 0x03, 0x4B, 0x45, 0x59, 0xFD, 0x00, 0xFD,
60 0x26, 0xFD, 0x00, 0xFE, 0x0F, 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x34, 0x54, 0x32, 0x32,
61 0x33, 0x37, 0x33, 0x39, 0xFD, 0x00, 0xFF, 0x0F, 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x38,
62 0x54, 0x32, 0x32, 0x33, 0x37, 0x33, 0x38
63};
64
65const uint8_t SIG_VALUE[] = {
66 0x17, 0x80, // SignatureValue
67 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
68 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
69 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
70 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
71 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
72 0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
73 0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
74 0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
75 0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
76 0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
77};
78
79const uint8_t CERT[] = {
80 0x06, 0xFD, 0x01, 0xBB, // Data
81 0x07, 0x33, // Name /ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B
82 0x08, 0x03, 0x6E, 0x64, 0x6E,
83 0x08, 0x05, 0x73, 0x69, 0x74, 0x65, 0x31,
84 0x08, 0x03, 0x4B, 0x45, 0x59,
85 0x08, 0x11,
86 0x6B, 0x73, 0x6B, 0x2D, 0x31, 0x34, 0x31, 0x36, 0x34, 0x32, 0x35, 0x33, 0x37, 0x37, 0x30, 0x39,
87 0x34,
88 0x08, 0x04, 0x30, 0x31, 0x32, 0x33,
89 0x08, 0x07, 0xFD, 0x00, 0x00, 0x01, 0x49, 0xC9, 0x8B,
90 0x14, 0x09, // MetaInfo
91 0x18, 0x01, 0x02, // ContentType = Key
92 0x19, 0x04, 0x00, 0x36, 0xEE, 0x80, // FreshnessPeriod = 3600000 ms
93 0x15, 0xA0, // Content
94 0x30, 0x81, 0x9D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
95 0x05, 0x00, 0x03, 0x81, 0x8B, 0x00, 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9E, 0x06, 0x3E,
96 0x47, 0x85, 0xB2, 0x34, 0x37, 0xAA, 0x85, 0x47, 0xAC, 0x03, 0x24, 0x83, 0xB5, 0x9C, 0xA8, 0x05,
97 0x3A, 0x24, 0x1E, 0xEB, 0x89, 0x01, 0xBB, 0xE9, 0x9B, 0xB2, 0xC3, 0x22, 0xAC, 0x68, 0xE3, 0xF0,
98 0x6C, 0x02, 0xCE, 0x68, 0xA6, 0xC4, 0xD0, 0xA7, 0x06, 0x90, 0x9C, 0xAA, 0x1B, 0x08, 0x1D, 0x8B,
99 0x43, 0x9A, 0x33, 0x67, 0x44, 0x6D, 0x21, 0xA3, 0x1B, 0x88, 0x9A, 0x97, 0x5E, 0x59, 0xC4, 0x15,
100 0x0B, 0xD9, 0x2C, 0xBD, 0x51, 0x07, 0x61, 0x82, 0xAD, 0xC1, 0xB8, 0xD7, 0xBF, 0x9B, 0xCF, 0x7D,
101 0x24, 0xC2, 0x63, 0xF3, 0x97, 0x17, 0xEB, 0xFE, 0x62, 0x25, 0xBA, 0x5B, 0x4D, 0x8A, 0xC2, 0x7A,
102 0xBD, 0x43, 0x8A, 0x8F, 0xB8, 0xF2, 0xF1, 0xC5, 0x6A, 0x30, 0xD3, 0x50, 0x8C, 0xC8, 0x9A, 0xDF,
103 0xEF, 0xED, 0x35, 0xE7, 0x7A, 0x62, 0xEA, 0x76, 0x7C, 0xBB, 0x08, 0x26, 0xC7, 0x02, 0x01, 0x11,
104 0x16, 0x55, // SignatureInfo
105 0x1B, 0x01, 0x01, // SignatureType
106 0x1C, 0x26, // KeyLocator: /ndn/site1/KEY/ksk-2516425377094
107 0x07, 0x24,
108 0x08, 0x03, 0x6E, 0x64, 0x6E,
109 0x08, 0x05, 0x73, 0x69, 0x74, 0x65, 0x31,
110 0x08, 0x03, 0x4B, 0x45, 0x59,
111 0x08, 0x11,
112 0x6B, 0x73, 0x6B, 0x2D, 0x32, 0x35, 0x31, 0x36, 0x34, 0x32, 0x35, 0x33, 0x37, 0x37, 0x30, 0x39,
113 0x34,
114 0xFD, 0x00, 0xFD, 0x26, // ValidityPeriod: (20150814T223739, 20150818T223738)
115 0xFD, 0x00, 0xFE, 0x0F,
116 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x34, 0x54, 0x32, 0x32, 0x33, 0x37, 0x33, 0x39,
117 0xFD, 0x00, 0xFF, 0x0F,
118 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x31, 0x38, 0x54, 0x32, 0x32, 0x33, 0x37, 0x33, 0x38,
119 0x17, 0x80, // SignatureValue
120 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
121 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
122 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
123 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
124 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
125 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
126 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
127 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
128};
129
130Signature
131generateFakeSignature()
132{
133 Block block1(SIG_INFO, sizeof(SIG_INFO));
134 SignatureInfo signatureInfo(block1);
135
136 Name keyLocatorName("/ndn/site1/KEY/ksk-2516425377094");
137 KeyLocator keyLocator(keyLocatorName);
138 signatureInfo.setKeyLocator(keyLocator);
139
140 ValidityPeriod period(time::fromIsoString("20141111T050000"), time::fromIsoString("20141111T060000"));
141 signatureInfo.setValidityPeriod(period);
142
143 Signature signature(signatureInfo);
144 Block block2(SIG_VALUE, sizeof(SIG_VALUE));
145 signature.setValue(block2);
146
147 return signature;
148}
149
150BOOST_AUTO_TEST_CASE(Construction)
151{
152 Block block(CERT, sizeof(CERT));
153 Certificate certificate(block);
154
155 BOOST_CHECK_EQUAL(certificate.getName(), "/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
156 BOOST_CHECK_EQUAL(certificate.getKeyName(), "/ndn/site1/KEY/ksk-1416425377094");
157 BOOST_CHECK_EQUAL(certificate.getIdentity(), "/ndn/site1");
158 BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
159 BOOST_CHECK_EQUAL(certificate.getKeyId(), name::Component("ksk-1416425377094"));
160 BOOST_CHECK_EQUAL(certificate.getSignature().getKeyLocator().getName(), "/ndn/site1/KEY/ksk-2516425377094");
161 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate.getValidityPeriod()), "(20150814T223739, 20150818T223738)");
162
163 BOOST_CHECK_THROW(certificate.getExtension(12345), ndn::SignatureInfo::Error);
164 BOOST_CHECK_NO_THROW(certificate.getPublicKey());
165
166 Data data(block);
167 Certificate certificate2(std::move(data));
168 BOOST_CHECK_EQUAL(certificate, certificate2);
169}
170
171BOOST_AUTO_TEST_CASE(Setters)
172{
173 Certificate certificate;
174 certificate.setName("/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
Davide Pesavento0f830802018-01-16 23:58:58 -0500175 certificate.setFreshnessPeriod(1_h);
Zhiyi Zhangf4bb5c72015-08-19 19:02:51 -0700176 certificate.setContent(PUBLIC_KEY, sizeof(PUBLIC_KEY));
177 certificate.setSignature(generateFakeSignature());
178
179 BOOST_CHECK_EQUAL(certificate.getName(), "/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
180 BOOST_CHECK_EQUAL(certificate.getKeyName(), "/ndn/site1/KEY/ksk-1416425377094");
181 BOOST_CHECK_EQUAL(certificate.getIdentity(), "/ndn/site1");
182 BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
183 BOOST_CHECK_EQUAL(certificate.getKeyId(), name::Component("ksk-1416425377094"));
184 BOOST_CHECK_EQUAL(certificate.getSignature().getKeyLocator().getName(), "/ndn/site1/KEY/ksk-2516425377094");
185 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate.getValidityPeriod()), "(20141111T050000, 20141111T060000)");
186
187 BOOST_CHECK_THROW(certificate.getExtension(12345), ndn::SignatureInfo::Error);
188 BOOST_CHECK_NO_THROW(certificate.getPublicKey());
189}
190
191BOOST_AUTO_TEST_CASE(ValidityPeriodChecking)
192{
193 Certificate certificate;
194 certificate.setName("/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
Davide Pesavento0f830802018-01-16 23:58:58 -0500195 certificate.setFreshnessPeriod(1_h);
Zhiyi Zhangf4bb5c72015-08-19 19:02:51 -0700196 certificate.setContent(PUBLIC_KEY, sizeof(PUBLIC_KEY));
197 certificate.setSignature(generateFakeSignature());
198
199 BOOST_CHECK_EQUAL(certificate.isValid(), true);
200 BOOST_CHECK_EQUAL(certificate.isValid(time::fromIsoString("20141111T045959")), false);
201 BOOST_CHECK_EQUAL(certificate.isValid(time::fromIsoString("20141111T060001")), false);
202}
203
204// This fixture prepares a well-formed certificate. A test case then modifies one of the
205// fields, and verifies the Certificate class correctly identifies the certificate as
206// malformed.
207class InvalidCertFixture
208{
209public:
210 InvalidCertFixture()
211 {
212 Certificate certBase(Block(CERT, sizeof(CERT)));
213 BOOST_CHECK_NO_THROW((Certificate(certBase)));
214
215 m_certBase = Data(certBase);
216 m_certBase.setSignature(generateFakeSignature());
217
218 BOOST_CHECK_NO_THROW((Certificate(m_certBase)));
219 }
220
221public:
222 Data m_certBase;
223};
224
225BOOST_FIXTURE_TEST_CASE(InvalidName, InvalidCertFixture)
226{
227 Data data(m_certBase);
228 data.setName("/ndn/site1/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
229 data.setSignature(generateFakeSignature());
230
231 BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
232 BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
233}
234
235BOOST_FIXTURE_TEST_CASE(InvalidType, InvalidCertFixture)
236{
237 Data data(m_certBase);
238 data.setContentType(tlv::ContentType_Blob);
239 data.setSignature(generateFakeSignature());
240
241 BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
242 BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
243}
244
245BOOST_FIXTURE_TEST_CASE(EmptyContent, InvalidCertFixture)
246{
247 Data data(m_certBase);
248 data.setContent(nullptr, 0);
249 data.setSignature(generateFakeSignature());
250
251 BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
252 BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
253
254 Certificate cert(m_certBase);
255 cert.setContent(nullptr, 0);
256 cert.setSignature(generateFakeSignature());
257 BOOST_CHECK_THROW(cert.getPublicKey(), Certificate::Error);
258}
259
Alexander Afanasyev5f1820e2017-01-04 18:12:42 -0800260BOOST_AUTO_TEST_CASE(PrintCertificateInfo)
261{
262 const std::string expectedCertificateInfo = std::string(R"INFO(
263Certificate name:
264 /ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B
265Validity:
266 NotBefore: 20150814T223739
267 NotAfter: 20150818T223738
268Public key bits:
269 MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCeBj5HhbI0N6qFR6wDJIO1nKgF
270 OiQe64kBu+mbssMirGjj8GwCzmimxNCnBpCcqhsIHYtDmjNnRG0hoxuImpdeWcQV
271 C9ksvVEHYYKtwbjXv5vPfSTCY/OXF+v+YiW6W02Kwnq9Q4qPuPLxxWow01CMyJrf
272 7+0153pi6nZ8uwgmxwIBEQ==
273Signature Information:
274 Signature Type: SignatureSha256WithRsa
275 Key Locator: Name=/ndn/site1/KEY/ksk-2516425377094
276)INFO").substr(1);
277
278 Certificate certificate(Block(CERT, sizeof(CERT)));
279 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate), expectedCertificateInfo);
280
281 // @todo Check output formats of other certificates
282}
283
Zhiyi Zhangf4bb5c72015-08-19 19:02:51 -0700284BOOST_AUTO_TEST_SUITE_END() // TestCertificate
285BOOST_AUTO_TEST_SUITE_END() // V2
286BOOST_AUTO_TEST_SUITE_END() // Security
287
288} // namespace tests
289} // namespace v2
290} // namespace security
291} // namespace ndn