ndn-cxx: NDN C++ Library 0.9.0-33-g832ea91d
Loading...
Searching...
No Matches
verification-helpers.cpp
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013-2023 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
23
24#include "ndn-cxx/data.hpp"
26#include "ndn-cxx/interest.hpp"
36
37#include <openssl/crypto.h>
38
39namespace ndn::security {
40
41namespace {
42
43class ParseResult
44{
45public:
46 ParseResult() = default;
47
48 ParseResult(SignatureInfo info, InputBuffers bufs, span<const uint8_t> sig)
49 : info(std::move(info))
50 , bufs(std::move(bufs))
51 , sig(sig)
52 {
53 }
54
55public:
56 SignatureInfo info;
57 InputBuffers bufs;
58 span<const uint8_t> sig;
59};
60
61} // namespace
62
63bool
64verifySignature(const InputBuffers& blobs, span<const uint8_t> sig, const transform::PublicKey& key)
65{
66 bool result = false;
67 try {
68 using namespace transform;
69 bufferSource(blobs) >> verifierFilter(DigestAlgorithm::SHA256, key, sig)
70 >> boolSink(result);
71 }
72 catch (const transform::Error&) {
73 return false;
74 }
75
76 return result;
77}
78
79bool
80verifySignature(const InputBuffers& blobs, span<const uint8_t> sig, span<const uint8_t> key)
81{
83 try {
84 pKey.loadPkcs8(key);
85 }
86 catch (const transform::Error&) {
87 return false;
88 }
89
90 return verifySignature(blobs, sig, pKey);
91}
92
93static ParseResult
94parse(const Data& data)
95{
96 try {
97 return {data.getSignatureInfo(), data.extractSignedRanges(),
99 }
100 catch (const tlv::Error&) {
101 return {};
102 }
103}
104
105static ParseResult
106parse(const Interest& interest)
107{
108 try {
109 interest.wireEncode();
110
111 if (interest.getSignatureInfo() && interest.getSignatureValue().isValid()) {
112 // Verify using v0.3 Signed Interest semantics
113 return {*interest.getSignatureInfo(), interest.extractSignedRanges(),
114 interest.getSignatureValue().value_bytes()};
115 }
116 else {
117 // Verify using older Signed Interest semantics
118 const Name& interestName = interest.getName();
119 if (interestName.size() < signed_interest::MIN_SIZE) {
120 return {};
121 }
122
123 const Block& nameBlock = interestName.wireEncode();
124 SignatureInfo info(interestName[signed_interest::POS_SIG_INFO].blockFromValue());
125 Block sigValue(interestName[signed_interest::POS_SIG_VALUE].blockFromValue());
126 return {info,
127 {{nameBlock.value(),
128 nameBlock.value_size() - interestName[signed_interest::POS_SIG_VALUE].size()}},
129 sigValue.value_bytes()};
130 }
131 }
132 catch (const tlv::Error&) {
133 return {};
134 }
135}
136
137static bool
138verifySignature(const ParseResult& params, const transform::PublicKey& key)
139{
140 return !params.bufs.empty() && verifySignature(params.bufs, params.sig, key);
141}
142
143static bool
144verifySignature(const ParseResult& params, span<const uint8_t> key)
145{
146 return !params.bufs.empty() && verifySignature(params.bufs, params.sig, key);
147}
148
149static bool
150verifySignature(const ParseResult& params, const tpm::Tpm& tpm, const Name& keyName,
151 DigestAlgorithm digestAlgorithm)
152{
153 return !params.bufs.empty() && bool(tpm.verify(params.bufs, params.sig, keyName, digestAlgorithm));
154}
155
156static bool
157verifyDigest(const ParseResult& params, DigestAlgorithm algorithm)
158{
159 if (params.bufs.empty()) {
160 return false;
161 }
162
163 OBufferStream os;
164 try {
165 using namespace transform;
166 bufferSource(params.bufs) >> digestFilter(algorithm) >> streamSink(os);
167 }
168 catch (const transform::Error&) {
169 return false;
170 }
171 auto result = os.buf();
172
173 if (result->size() != params.sig.size()) {
174 return false;
175 }
176
177 // constant-time buffer comparison to mitigate timing attacks
178 return CRYPTO_memcmp(result->data(), params.sig.data(), params.sig.size()) == 0;
179}
180
181bool
182verifySignature(const Data& data, span<const uint8_t> key)
183{
184 return verifySignature(parse(data), key);
185}
186
187bool
188verifySignature(const Interest& interest, span<const uint8_t> key)
189{
190 return verifySignature(parse(interest), key);
191}
192
193bool
195{
196 return verifySignature(parse(data), key);
197}
198
199bool
201{
202 return verifySignature(parse(interest), key);
203}
204
205bool
206verifySignature(const Data& data, const pib::Key& key)
207{
208 return verifySignature(parse(data), key.getPublicKey());
209}
210
211bool
212verifySignature(const Interest& interest, const pib::Key& key)
213{
214 return verifySignature(parse(interest), key.getPublicKey());
215}
216
217bool
218verifySignature(const Data& data, const std::optional<Certificate>& cert)
219{
220 auto parsed = parse(data);
221 if (cert) {
222 return verifySignature(parsed, cert->getPublicKey());
223 }
224 else if (parsed.info.getSignatureType() == tlv::SignatureTypeValue::DigestSha256) {
225 return verifyDigest(parsed, DigestAlgorithm::SHA256);
226 }
227 // Add any other self-verifying signatures here (if any)
228 else {
229 return false;
230 }
231}
232
233bool
234verifySignature(const Interest& interest, const std::optional<Certificate>& cert)
235{
236 auto parsed = parse(interest);
237 if (cert) {
238 return verifySignature(parsed, cert->getPublicKey());
239 }
240 else if (parsed.info.getSignatureType() == tlv::SignatureTypeValue::DigestSha256) {
241 return verifyDigest(parsed, DigestAlgorithm::SHA256);
242 }
243 // Add any other self-verifying signatures here (if any)
244 else {
245 return false;
246 }
247}
248
249bool
250verifySignature(const Data& data, const tpm::Tpm& tpm,
251 const Name& keyName, DigestAlgorithm digestAlgorithm)
252{
253 return verifySignature(parse(data), tpm, keyName, digestAlgorithm);
254}
255
256bool
257verifySignature(const Interest& interest, const tpm::Tpm& tpm,
258 const Name& keyName, DigestAlgorithm digestAlgorithm)
259{
260 return verifySignature(parse(interest), tpm, keyName, digestAlgorithm);
261}
262
263} // namespace ndn::security
span< const uint8_t > value_bytes() const noexcept
Return a read-only view of TLV-VALUE as a contiguous range of bytes.
Definition block.hpp:308
Represents a Data packet.
Definition data.hpp:39
const Block & getSignatureValue() const noexcept
Get the SignatureValue element.
Definition data.hpp:265
InputBuffers extractSignedRanges() const
Extract ranges of Data covered by the signature.
Definition data.cpp:323
const SignatureInfo & getSignatureInfo() const noexcept
Get the SignatureInfo element.
Definition data.hpp:243
Represents an Interest packet.
Definition interest.hpp:50
Represents an absolute name.
Definition name.hpp:45
Frontend handle for a key in the PIB.
Definition key.hpp:45
span< const uint8_t > getPublicKey() const
Return the raw public key bits.
Definition key.cpp:54
TPM front-end class.
Definition tpm.hpp:63
Base class of transformation error.
Abstraction of a public key in crypto transformations.
void loadPkcs8(span< const uint8_t > buf)
Load the public key in PKCS#8 format from a buffer buf.
unique_ptr< Transform > digestFilter(DigestAlgorithm algo)
unique_ptr< Sink > streamSink(std::ostream &os)
Contains the ndn-cxx security framework.
bool verifySignature(const InputBuffers &blobs, span< const uint8_t > sig, const transform::PublicKey &key)
Verify blobs using key against sig.
constexpr ssize_t POS_SIG_VALUE
constexpr size_t MIN_SIZE
Minimum number of name components for an old-style Signed Interest.
constexpr ssize_t POS_SIG_INFO
@ Name
Definition tlv.hpp:71
@ SignatureInfo
Definition tlv.hpp:94
@ DigestSha256
Definition tlv.hpp:128
STL namespace.
InputBuffers bufs
span< const uint8_t > sig
SignatureInfo info