blob: f8fd3d2584f6da4a75ccd859b3143147bdf615fb [file] [log] [blame]
Alexander Afanasyev574aa862017-01-10 19:53:28 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2017 Regents of the University of California.
4 *
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 "verification-helpers.hpp"
23
24#include "data.hpp"
25#include "interest.hpp"
26#include "encoding/buffer-stream.hpp"
27#include "security/pib/key.hpp"
28#include "security/pib/key.hpp"
29#include "security/transform.hpp"
30#include "security/v2/certificate.hpp"
31#include "security/detail/openssl.hpp"
32
33namespace ndn {
34namespace security {
35
36bool
37verifySignature(const uint8_t* blob, size_t blobLen, const uint8_t* sig, size_t sigLen,
38 const v2::PublicKey& pKey)
39{
40 bool result = false;
41 try {
42 using namespace transform;
43 bufferSource(blob, blobLen) >> verifierFilter(DigestAlgorithm::SHA256, pKey, sig, sigLen)
44 >> boolSink(result);
45 }
46 catch (const transform::Error&) {
47 return false;
48 }
49 return result;
50}
51
52bool
53verifySignature(const uint8_t* data, size_t dataLen, const uint8_t* sig, size_t sigLen,
54 const uint8_t* key, size_t keyLen)
55{
56 v2::PublicKey pKey;
57 try {
58 pKey.loadPkcs8(key, keyLen);
59 }
60 catch (const transform::Error&) {
61 return false;
62 }
63
64 return verifySignature(data, dataLen, sig, sigLen, pKey);
65}
66
67static std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>
68parse(const Data& data)
69{
70 try {
71 return std::make_tuple(true,
72 data.wireEncode().value(),
73 data.wireEncode().value_size() - data.getSignature().getValue().size(),
74 data.getSignature().getValue().value(),
75 data.getSignature().getValue().value_size());
76 }
77 catch (const tlv::Error&) {
78 return std::make_tuple(false, nullptr, 0, nullptr, 0);
79 }
80}
81
82static std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>
83parse(const Interest& interest)
84{
85 const Name& interestName = interest.getName();
86
87 if (interestName.size() < signed_interest::MIN_SIZE)
88 return std::make_tuple(false, nullptr, 0, nullptr, 0);
89
90 try {
91 const Block& nameBlock = interestName.wireEncode();
92
93 return std::make_tuple(true,
94 nameBlock.value(), nameBlock.value_size() - interestName[signed_interest::POS_SIG_VALUE].size(),
95 interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value(),
96 interestName[signed_interest::POS_SIG_VALUE].blockFromValue().value_size());
97 }
98 catch (const tlv::Error&) {
99 return std::make_tuple(false, nullptr, 0, nullptr, 0);
100 }
101}
102
103static bool
104verifySignature(const std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>& params,
105 const v2::PublicKey& pKey)
106{
107 bool isParsable = false;
108 const uint8_t* buf = nullptr;
109 size_t bufLen = 0;
110 const uint8_t* sig = nullptr;
111 size_t sigLen = 0;
112
113 std::tie(isParsable, buf, bufLen, sig, sigLen) = params;
114
115 if (isParsable)
116 return verifySignature(buf, bufLen, sig, sigLen, pKey);
117 else
118 return false;
119}
120
121static bool
122verifySignature(const std::tuple<bool, const uint8_t*, size_t, const uint8_t*, size_t>& params,
123 const uint8_t* key, size_t keyLen)
124{
125 bool isParsable = false;
126 const uint8_t* buf = nullptr;
127 size_t bufLen = 0;
128 const uint8_t* sig = nullptr;
129 size_t sigLen = 0;
130
131 std::tie(isParsable, buf, bufLen, sig, sigLen) = params;
132
133 if (isParsable)
134 return verifySignature(buf, bufLen, sig, sigLen, key, keyLen);
135 else
136 return false;
137}
138
139bool
140verifySignature(const Data& data, const v2::PublicKey& key)
141{
142 return verifySignature(parse(data), key);
143}
144
145bool
146verifySignature(const Interest& interest, const v2::PublicKey& key)
147{
148 return verifySignature(parse(interest), key);
149}
150
151bool
152verifySignature(const Data& data, const pib::Key& key)
153{
154 return verifySignature(parse(data), key.getPublicKey().buf(), key.getPublicKey().size());
155}
156
157bool
158verifySignature(const Interest& interest, const pib::Key& key)
159{
160 return verifySignature(parse(interest), key.getPublicKey().buf(), key.getPublicKey().size());
161}
162
163bool
164verifySignature(const Data& data, const uint8_t* key, size_t keyLen)
165{
166 return verifySignature(parse(data), key, keyLen);
167}
168
169bool
170verifySignature(const Interest& interest, const uint8_t* key, size_t keyLen)
171{
172 return verifySignature(parse(interest), key, keyLen);
173}
174
175bool
176verifySignature(const Data& data, const v2::Certificate& cert)
177{
178 return verifySignature(parse(data), cert.getContent().value(), cert.getContent().value_size());
179}
180
181bool
182verifySignature(const Interest& interest, const v2::Certificate& cert)
183{
184 return verifySignature(parse(interest), cert.getContent().value(), cert.getContent().value_size());
185}
186
187///////////////////////////////////////////////////////////////////////
188
189bool
190verifyDigest(const uint8_t* blob, size_t blobLen, const uint8_t* digest, size_t digestLen,
191 DigestAlgorithm algorithm)
192{
193 using namespace transform;
194
195 OBufferStream os;
196 try {
197 bufferSource(blob, blobLen) >> digestFilter(algorithm) >> streamSink(os);
198 }
199 catch (const transform::Error&) {
200 return false;
201 }
202 ConstBufferPtr result = os.buf();
203
204 if (result->size() != digestLen)
205 return false;
206
207 // constant-time buffer comparison to mitigate timing attacks
208 return CRYPTO_memcmp(result->buf(), digest, digestLen) == 0;
209}
210
211bool
212verifyDigest(const Data& data, DigestAlgorithm algorithm)
213{
214 bool isParsable = false;
215 const uint8_t* buf = nullptr;
216 size_t bufLen = 0;
217 const uint8_t* sig = nullptr;
218 size_t sigLen = 0;
219
220 std::tie(isParsable, buf, bufLen, sig, sigLen) = parse(data);
221
222 if (isParsable) {
223 return verifyDigest(buf, bufLen, sig, sigLen, algorithm);
224 }
225 else {
226 return false;
227 }
228}
229
230bool
231verifyDigest(const Interest& interest, DigestAlgorithm algorithm)
232{
233 bool isParsable = false;
234 const uint8_t* buf = nullptr;
235 size_t bufLen = 0;
236 const uint8_t* sig = nullptr;
237 size_t sigLen = 0;
238
239 std::tie(isParsable, buf, bufLen, sig, sigLen) = parse(interest);
240
241 if (isParsable) {
242 return verifyDigest(buf, bufLen, sig, sigLen, algorithm);
243 }
244 else {
245 return false;
246 }
247}
248
249} // namespace security
250} // namespace ndn