blob: 62f660d936c754554484f750cdbb025cf0f994da [file] [log] [blame]
Yingdi Yu2abd73f2014-01-08 23:34:11 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
6 * See COPYING for copyright and distribution information.
7 */
8
9#if __clang__
10#pragma clang diagnostic push
11#pragma clang diagnostic ignored "-Wreorder"
12#pragma clang diagnostic ignored "-Wtautological-compare"
13#pragma clang diagnostic ignored "-Wunused-variable"
14#pragma clang diagnostic ignored "-Wunused-function"
15#elif __GNUC__
16#pragma GCC diagnostic ignored "-Wreorder"
17#pragma GCC diagnostic ignored "-Wunused-variable"
18#pragma GCC diagnostic ignored "-Wunused-function"
19#endif
20
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080021#include "security/verifier.hpp"
Yingdi Yu2abd73f2014-01-08 23:34:11 -080022
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080023#include "security/sec-policy.hpp"
Yingdi Yu2abd73f2014-01-08 23:34:11 -080024
25#include <cryptopp/rsa.h>
26
27#include "../util/logging.hpp"
28
29using namespace std;
Yingdi Yu2abd73f2014-01-08 23:34:11 -080030#if NDN_CPP_HAVE_CXX11
31// In the std library, the placeholders are in a different namespace than boost.
32using namespace ndn::func_lib::placeholders;
33#endif
34
35INIT_LOGGER("ndn.Verifier");
36
37namespace ndn {
Yingdi Yu4f324632014-01-15 18:10:03 -080038const ptr_lib::shared_ptr<SecPolicy> Verifier::DefaultPolicy = ptr_lib::shared_ptr<SecPolicy>();
Yingdi Yu2abd73f2014-01-08 23:34:11 -080039
Yingdi Yu4f324632014-01-15 18:10:03 -080040Verifier::Verifier(const ptr_lib::shared_ptr<SecPolicy> &policy /* = DefaultPolicy */)
Yingdi Yue07e3392014-01-28 10:29:27 -080041 : m_policy(policy)
Yingdi Yu2abd73f2014-01-08 23:34:11 -080042{
Yingdi Yue07e3392014-01-28 10:29:27 -080043 if (m_policy == DefaultPolicy)
Yingdi Yu2abd73f2014-01-08 23:34:11 -080044 {
45 // #ifdef USE_SIMPLE_POLICY_MANAGER
46 // Ptr<SimplePolicyManager> policyManager = Ptr<SimplePolicyManager>(new SimplePolicyManager());
47 // Ptr<IdentityPolicyRule> rule1 = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
48 // "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
49 // ">", "\\1\\2", "\\1", true));
50 // Ptr<IdentityPolicyRule> rule2 = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
51 // "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
52 // "==", "\\1", "\\1\\2", true));
53 // Ptr<IdentityPolicyRule> rule3 = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^(<>*)$",
54 // "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
55 // ">", "\\1", "\\1", true));
56 // policyManager->addVerificationPolicyRule(rule1);
57 // policyManager->addVerificationPolicyRule(rule2);
58 // policyManager->addVerificationPolicyRule(rule3);
59
60 // policyManager->addSigningPolicyRule(rule3);
61
62 // m_policyManager = policyManager;
63 //
64 // #else
Yingdi Yu4f324632014-01-15 18:10:03 -080065 // policy_ = new NoVerifyPolicyManager();
Yingdi Yu2abd73f2014-01-08 23:34:11 -080066 // #endif
67 }
68}
69
70void
Yingdi Yue07e3392014-01-28 10:29:27 -080071Verifier::verify(const ptr_lib::shared_ptr<const Interest> &interest,
72 const OnVerified &onVerified,
73 const OnVerifyFailed &onVerifyFailed,
74 int stepCount)
Yingdi Yu2abd73f2014-01-08 23:34:11 -080075{
Yingdi Yue07e3392014-01-28 10:29:27 -080076 //It does not make sense to verify Interest without specified policy, verification must fail!
77 if(!static_cast<bool>(m_policy))
78 onVerifyFailed();
Yingdi Yu2abd73f2014-01-08 23:34:11 -080079 else
Yingdi Yue07e3392014-01-28 10:29:27 -080080 {
81 //check verification policy
82 ptr_lib::shared_ptr<ValidationRequest> nextStep = m_policy->checkVerificationPolicy(interest, stepCount, onVerified, onVerifyFailed);
83 if (static_cast<bool>(nextStep))
84 {
85 if(!m_face)
86 throw Error("Face should be set prior to verify method to call");
87
88 m_face->expressInterest
89 (*nextStep->m_interest,
90 func_lib::bind(&Verifier::onCertificateData, this, _1, _2, nextStep),
91 func_lib::bind(&Verifier::onCertificateInterestTimeout, this, _1, nextStep->m_retry, onVerifyFailed, nextStep));
92 }
93 else
94 {
95 //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
96 //No more further processes.
97 }
98 }
Yingdi Yu2abd73f2014-01-08 23:34:11 -080099}
100
101void
Yingdi Yue07e3392014-01-28 10:29:27 -0800102Verifier::verify(const ptr_lib::shared_ptr<const Data> &data,
103 const OnVerified &onVerified,
104 const OnVerifyFailed &onVerifyFailed,
105 int stepCount)
106{
107 //It does not make sense to verify Interest without specified policy, verification must fail!
108 if(!static_cast<bool>(m_policy))
109 onVerifyFailed();
110 else
111 {
112 //check verification policy
113 ptr_lib::shared_ptr<ValidationRequest> nextStep = m_policy->checkVerificationPolicy(data, stepCount, onVerified, onVerifyFailed);
114 if (static_cast<bool>(nextStep))
115 {
116 if(!m_face)
117 throw Error("Face should be set prior to verify method to call");
118
119 m_face->expressInterest
120 (*nextStep->m_interest,
121 func_lib::bind(&Verifier::onCertificateData, this, _1, _2, nextStep),
122 func_lib::bind(&Verifier::onCertificateInterestTimeout, this, _1, nextStep->m_retry, onVerifyFailed, nextStep));
123 }
124 else
125 {
126 //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
127 //No more further processes.
128 }
129 }
130}
131
132void
133Verifier::onCertificateData(const ptr_lib::shared_ptr<const Interest> &interest,
134 const ptr_lib::shared_ptr<Data> &data,
135 ptr_lib::shared_ptr<ValidationRequest> nextStep)
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800136{
137 // Try to verify the certificate (data) according to the parameters in nextStep.
Yingdi Yue07e3392014-01-28 10:29:27 -0800138 verify(data,
139 func_lib::bind(nextStep->m_onVerified, data),
140 func_lib::bind(nextStep->m_onVerifyFailed, data),
141 nextStep->m_stepCount);
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800142}
143
144void
145Verifier::onCertificateInterestTimeout
Yingdi Yue07e3392014-01-28 10:29:27 -0800146 (const ptr_lib::shared_ptr<const Interest> &interest, int retry, const OnVerifyFailed& onVerifyFailed, ptr_lib::shared_ptr<ValidationRequest> nextStep)
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800147{
148 if (retry > 0)
149 // Issue the same expressInterest as in verifyData except decrement retry.
Yingdi Yue07e3392014-01-28 10:29:27 -0800150 m_face->expressInterest
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800151 (*interest,
Yingdi Yue07e3392014-01-28 10:29:27 -0800152 func_lib::bind(&Verifier::onCertificateData, this, _1, _2, nextStep),
153 func_lib::bind(&Verifier::onCertificateInterestTimeout, this, _1, retry - 1, onVerifyFailed, nextStep));
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800154 else
Yingdi Yue07e3392014-01-28 10:29:27 -0800155 onVerifyFailed();
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800156}
157
158bool
Yingdi Yu913b0c72014-01-10 18:02:55 -0800159Verifier::verifySignature(const Data& data, const Signature& sig, const PublicKey& key)
160{
161 try{
162 switch(sig.getType()){
163 case Signature::Sha256WithRsa:
164 {
165 SignatureSha256WithRsa sigSha256Rsa(sig);
166 return verifySignature(data, sigSha256Rsa, key);
167 }
168 default:
169 {
170 _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
171 return false;
172 }
173 }
174 }catch(Signature::Error &e){
175 _LOG_DEBUG("verifySignature: " << e.what());
176 return false;
177 }
178 return false;
179}
180
181bool
Yingdi Yu4270f202014-01-28 14:19:16 -0800182Verifier::verifySignature(const Interest &interest, const PublicKey &key)
183{
184 const Name &interestName = interest.getName();
185
186 if(interestName.size() < 3)
187 return false;
188
189 try{
190 const Block &nameBlock = interestName.wireEncode();
191
192 if(nameBlock.getAll().size() != interestName.size()) //HACK!! we should change it when Name::Component is changed to derive from Block.
193 const_cast<Block&>(nameBlock).parse();
194
195 Signature sig((++nameBlock.getAll().rbegin())->blockFromValue(),
196 (nameBlock.getAll().rbegin())->blockFromValue());
197
198 switch(sig.getType()){
199 case Signature::Sha256WithRsa:
200 {
201 SignatureSha256WithRsa sigSha256Rsa(sig);
202
203 return verifySignature(nameBlock.value(),
204 nameBlock.value_size() - (nameBlock.getAll().rbegin())->size(),
205 sigSha256Rsa, key);
206 }
207 default:
208 {
209 _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
210 return false;
211 }
212 }
213 }catch(Signature::Error &e){
214 _LOG_DEBUG("verifySignature: " << e.what());
215 return false;
216 }catch(Block::Error &e){
217 _LOG_DEBUG("verifySignature: " << e.what());
218 return false;
219 }
220 return false;
221}
222
223bool
Yingdi Yu913b0c72014-01-10 18:02:55 -0800224Verifier::verifySignature(const Buffer &data, const Signature &sig, const PublicKey &key)
225{
226 try{
227 switch(sig.getType()){
228 case Signature::Sha256WithRsa:
229 {
230 SignatureSha256WithRsa sigSha256Rsa(sig);
231 return verifySignature(data, sigSha256Rsa, key);
232 }
233 default:
234 {
235 _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
236 return false;
237 }
238 }
239 }catch(Signature::Error &e){
240 _LOG_DEBUG("verifySignature: " << e.what());
241 return false;
242 }
243 return false;
244}
245
246bool
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800247Verifier::verifySignature(const Data& data, const SignatureSha256WithRsa& sig, const PublicKey& key)
248{
249 using namespace CryptoPP;
250
251 bool result = false;
252
253 RSA::PublicKey publicKey;
254 ByteQueue queue;
255
256 queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
257 publicKey.Load(queue);
258
259 RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
260 result = verifier.VerifyMessage(data.wireEncode().value(), data.wireEncode().value_size() - data.getSignature().getValue().size(),
261 sig.getValue().value(), sig.getValue().value_size());
262
263 _LOG_DEBUG("Signature verified? " << data.getName().toUri() << " " << boolalpha << result);
264
265 return result;
266}
267
Yingdi Yu913b0c72014-01-10 18:02:55 -0800268bool
269Verifier::verifySignature(const Buffer& data, const SignatureSha256WithRsa& sig, const PublicKey& key)
270{
271 using namespace CryptoPP;
272
273 bool result = false;
274
275 RSA::PublicKey publicKey;
276 ByteQueue queue;
277
278 queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
279 publicKey.Load(queue);
280
281 RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
282 result = verifier.VerifyMessage(data.buf(), data.size(),
283 sig.getValue().value(), sig.getValue().value_size());
Yingdi Yu4270f202014-01-28 14:19:16 -0800284
285 return result;
286}
Yingdi Yu913b0c72014-01-10 18:02:55 -0800287
Yingdi Yu4270f202014-01-28 14:19:16 -0800288bool
289Verifier::verifySignature(const uint8_t* buf, const size_t size, const SignatureSha256WithRsa &sig, const PublicKey &key)
290{
291 using namespace CryptoPP;
292
293 bool result = false;
294
295 RSA::PublicKey publicKey;
296 ByteQueue queue;
297
298 queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
299 publicKey.Load(queue);
300
301 RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
302 result = verifier.VerifyMessage(buf, size, sig.getValue().value(), sig.getValue().value_size());
Yingdi Yu913b0c72014-01-10 18:02:55 -0800303
304 return result;
305}
306
Yingdi Yu2abd73f2014-01-08 23:34:11 -0800307}