blob: ce17b04ad44438862b73562ab83684e68169c81b [file] [log] [blame]
peizhen guo0401e3e2014-08-12 13:24:30 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07003 * Copyright (c) 2014-2017, Regents of the University of California
peizhen guo0401e3e2014-08-12 13:24:30 -07004 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07005 * This file is part of NDN DeLorean, An Authentication System for Data Archives in
6 * Named Data Networking. See AUTHORS.md for complete list of NDN DeLorean authors
7 * and contributors.
peizhen guo0401e3e2014-08-12 13:24:30 -07008 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07009 * NDN DeLorean is free software: you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
peizhen guo0401e3e2014-08-12 13:24:30 -070013 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -070014 * NDN DeLorean is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
peizhen guo0401e3e2014-08-12 13:24:30 -070017 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -070018 * You should have received a copy of the GNU General Public License along with NDN
19 * DeLorean, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
peizhen guo0401e3e2014-08-12 13:24:30 -070020 */
Yingdi Yu0c3e5912015-03-17 14:22:38 -070021
peizhen guo0401e3e2014-08-12 13:24:30 -070022#include "auditor.hpp"
23
Yingdi Yu0c3e5912015-03-17 14:22:38 -070024#include <ndn-cxx/util/digest.hpp>
25
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -070026namespace ndn {
27namespace delorean {
peizhen guo0401e3e2014-08-12 13:24:30 -070028
Yingdi Yu0c3e5912015-03-17 14:22:38 -070029bool
30Auditor::doesExist(const NonNegativeInteger& seqNo,
31 ndn::ConstBufferPtr hash,
32 const NonNegativeInteger& rootNextSeqNo,
33 ndn::ConstBufferPtr rootHash,
34 const std::vector<shared_ptr<Data>>& proofs,
35 const Name& loggerName)
peizhen guo0401e3e2014-08-12 13:24:30 -070036{
Yingdi Yu0c3e5912015-03-17 14:22:38 -070037 BOOST_ASSERT(rootHash != nullptr);
38 BOOST_ASSERT(hash != nullptr);
39
40 std::map<Node::Index, ConstSubTreeBinaryPtr> trees;
41
42 if (!loadProof(trees, proofs, loggerName))
43 return false;
44
45 // std::cerr << "Loaded" << std::endl;
46
47 size_t rootLevel = 0;
48 NonNegativeInteger tmpSeqNo = rootNextSeqNo - 1;
49 while (tmpSeqNo != 0) {
50 rootLevel++;
51 tmpSeqNo = tmpSeqNo >> 1;
52 }
53
54 if (rootLevel == 0) { // only one node
55 // std::cerr << "one level" << std::endl;
56 if (seqNo != 0)
57 return false;
58
59 auto it = trees.find(Node::Index(0, SubTreeBinary::SUB_TREE_DEPTH - 1));
60 if (it != trees.end()) {
61 // std::cerr << "find subtree" << std::endl;
62 auto node = it->second->getNode(Node::Index(0, 0));
63 if (node != nullptr && *node->getHash() == *hash && *hash == *rootHash)
64 return true;
65 else
66 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -070067 }
Yingdi Yu0c3e5912015-03-17 14:22:38 -070068 else
69 return false;
70 }
71
72
73 NonNegativeInteger childSeqMask = 1;
74 NonNegativeInteger childSeqNo = seqNo;
75 size_t childLevel = 0;
76 ndn::ConstBufferPtr childHash = hash;
77
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -070078 NonNegativeInteger parentSeqMask = (~0ul) << 1;
Yingdi Yu0c3e5912015-03-17 14:22:38 -070079 NonNegativeInteger parentSeqNo = childSeqNo & parentSeqMask;
80 size_t parentLevel = 1;
81
82 Node::Index treePeakIndex(0, 0);
83 ConstSubTreeBinaryPtr subTree;
84
85 do { // get parent hash
86 Node::Index tmpIndex =
87 SubTreeBinary::toSubTreePeakIndex(Node::Index(childSeqNo, childLevel));
88
89 // std::cerr << "peak: " << tmpIndex.level << ", " << tmpIndex.seqNo << std::endl;
90 if (tmpIndex != treePeakIndex) {
91 treePeakIndex = tmpIndex;
92 auto it = trees.find(treePeakIndex);
93 if (it != trees.end() && it->second != nullptr) {
94 subTree = it->second;
95 }
96 else
97 return false;
98 }
99
100 // std::cerr << "Hey" << std::endl;
101 // right child or left child
102 ndn::util::Sha256 sha256;
103 if (childSeqMask & seqNo) { // right child
104 // std::cerr << "right" << std::endl;
105 // std::cerr << parentSeqNo << ", " << childLevel << std::endl;
106 auto leftChild = subTree->getNode(Node::Index(parentSeqNo, childLevel));
107 if (leftChild == nullptr && leftChild->getHash() == nullptr)
108 return false;
109
110 // std::cerr << "found node" << std::endl;
111 sha256 << parentLevel << parentSeqNo;
112 sha256.update(leftChild->getHash()->buf(), leftChild->getHash()->size());
113 sha256.update(childHash->buf(), childHash->size());
114 }
115 else { // left child
116 // std::cerr << "left" << std::endl;
117 ndn::ConstBufferPtr rightChildHash = Node::getEmptyHash();
118 if (rootNextSeqNo > childSeqNo + (1 << childLevel)) {
119 // std::cerr << childSeqNo + (1 << childLevel) << ", " << childLevel << std::endl;
120 auto rightChild = subTree->getNode(Node::Index(childSeqNo + (1 << childLevel), childLevel));
121 if (rightChild == nullptr || rightChild->getHash() == nullptr)
122 return false;
123 rightChildHash = rightChild->getHash();
124 // std::cerr << "left done" << std::endl;
125 }
126
127 sha256 << parentLevel << parentSeqNo;
128 sha256.update(childHash->buf(), childHash->size());
129 sha256.update(rightChildHash->buf(), rightChildHash->size());
130 }
131
132 childSeqMask = childSeqMask << 1;
133 childSeqNo = parentSeqNo;
134 childLevel = parentLevel;
135 childHash = sha256.computeDigest();
136
137 parentSeqMask = parentSeqMask << 1;
138 parentSeqNo = childSeqNo & parentSeqMask;
139 parentLevel++;
140
141 } while (childLevel < rootLevel);
142
143 // std::cerr << "done" << std::endl;
144
145 return (*childHash == *rootHash);
peizhen guo0401e3e2014-08-12 13:24:30 -0700146}
147
peizhen guo0401e3e2014-08-12 13:24:30 -0700148bool
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700149Auditor::isConsistent(const NonNegativeInteger& oldRootNextSeqNo,
150 ndn::ConstBufferPtr oldRootHash,
151 const NonNegativeInteger& newRootNextSeqNo,
152 ndn::ConstBufferPtr newRootHash,
153 const std::vector<shared_ptr<Data>>& proofs,
154 const Name& loggerName)
peizhen guo0401e3e2014-08-12 13:24:30 -0700155{
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700156 BOOST_ASSERT(oldRootHash != nullptr);
157 BOOST_ASSERT(newRootHash != nullptr);
peizhen guo0401e3e2014-08-12 13:24:30 -0700158
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700159 if (oldRootNextSeqNo > newRootNextSeqNo)
160 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700161
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700162 std::map<Node::Index, ConstSubTreeBinaryPtr> trees;
163 if (!loadProof(trees, proofs, loggerName))
164 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700165
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700166 // std::cerr << "1" << std::endl;
peizhen guo0401e3e2014-08-12 13:24:30 -0700167
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700168 // get boundary leaf:
169 NonNegativeInteger leafSeqNo = oldRootNextSeqNo - 1;
170 NonNegativeInteger treeSeqNo = leafSeqNo & ((~0) << (SubTreeBinary::SUB_TREE_DEPTH - 1));
171 auto it = trees.find(Node::Index(treeSeqNo, SubTreeBinary::SUB_TREE_DEPTH - 1));
172 if (it == trees.end())
173 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700174
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700175 auto leaf = it->second->getNode(Node::Index(leafSeqNo, 0));
176 if (leaf == nullptr || leaf->getHash() == nullptr)
177 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700178
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700179 if (!doesExist(leafSeqNo, leaf->getHash(), oldRootNextSeqNo, oldRootHash,
180 proofs, loggerName))
181 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700182
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700183 // std::cerr << "2" << std::endl;
peizhen guo0401e3e2014-08-12 13:24:30 -0700184
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700185 if (oldRootNextSeqNo == newRootNextSeqNo) {
186 if (*oldRootHash == *newRootHash)
187 return true;
188 else
189 return false;
190 }
191
192 // std::cerr << "3" << std::endl;
193
194 if (!doesExist(leafSeqNo, leaf->getHash(), newRootNextSeqNo, newRootHash,
195 proofs, loggerName))
196 return false;
197
198 // std::cerr << "4" << std::endl;
199
200 return true;
peizhen guo0401e3e2014-08-12 13:24:30 -0700201}
202
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700203bool
204Auditor::loadProof(std::map<Node::Index, ConstSubTreeBinaryPtr>& trees,
205 const std::vector<shared_ptr<Data>>& proofs,
206 const Name& loggerName)
207{
208 try {
209 for (auto proof : proofs) {
210 // std::cerr << proof->getName() << std::endl;
211 auto subtree =
212 make_shared<SubTreeBinary>(loggerName,
213 [] (const Node::Index& idx) {},
214 [] (const Node::Index&,
215 const NonNegativeInteger& seqNo,
216 ndn::ConstBufferPtr hash) {});
217 subtree->decode(*proof);
218
219 // std::cerr << subtree->getPeakIndex().level << ", " << subtree->getPeakIndex().seqNo << std::endl;
220 if (trees.find(subtree->getPeakIndex()) == trees.end())
221 trees[subtree->getPeakIndex()] = subtree;
222 else
223 return false;
224 }
225 }
226 catch (SubTreeBinary::Error& e) {
227 // std::cerr << e.what() << std::endl;
228 return false;
229 }
230 catch (Node::Error& e) {
231 // std::cerr << e.what() << std::endl;
232 return false;
233 }
234 catch (tlv::Error&) {
235 return false;
236 }
237
238 return true;
239}
peizhen guo0401e3e2014-08-12 13:24:30 -0700240
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -0700241} // namespace delorean
242} // namespace ndn