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