blob: 34f85d01d75bf97b171fa76af04a946370de1056 [file] [log] [blame]
peizhen guo0401e3e2014-08-12 13:24:30 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014, Regents of the University of California
4 *
5 * This file is part of NSL (NDN Signature Logger).
6 * See AUTHORS.md for complete list of NSL authors and contributors.
7 *
8 * NSL is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NSL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
Yingdi Yu0c3e5912015-03-17 14:22:38 -070019 * See AUTHORS.md for complete list of nsl authors and contributors.
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
peizhen guo0401e3e2014-08-12 13:24:30 -070026namespace nsl {
27
Yingdi Yu0c3e5912015-03-17 14:22:38 -070028bool
29Auditor::doesExist(const NonNegativeInteger& seqNo,
30 ndn::ConstBufferPtr hash,
31 const NonNegativeInteger& rootNextSeqNo,
32 ndn::ConstBufferPtr rootHash,
33 const std::vector<shared_ptr<Data>>& proofs,
34 const Name& loggerName)
peizhen guo0401e3e2014-08-12 13:24:30 -070035{
Yingdi Yu0c3e5912015-03-17 14:22:38 -070036 BOOST_ASSERT(rootHash != nullptr);
37 BOOST_ASSERT(hash != nullptr);
38
39 std::map<Node::Index, ConstSubTreeBinaryPtr> trees;
40
41 if (!loadProof(trees, proofs, loggerName))
42 return false;
43
44 // std::cerr << "Loaded" << std::endl;
45
46 size_t rootLevel = 0;
47 NonNegativeInteger tmpSeqNo = rootNextSeqNo - 1;
48 while (tmpSeqNo != 0) {
49 rootLevel++;
50 tmpSeqNo = tmpSeqNo >> 1;
51 }
52
53 if (rootLevel == 0) { // only one node
54 // std::cerr << "one level" << std::endl;
55 if (seqNo != 0)
56 return false;
57
58 auto it = trees.find(Node::Index(0, SubTreeBinary::SUB_TREE_DEPTH - 1));
59 if (it != trees.end()) {
60 // std::cerr << "find subtree" << std::endl;
61 auto node = it->second->getNode(Node::Index(0, 0));
62 if (node != nullptr && *node->getHash() == *hash && *hash == *rootHash)
63 return true;
64 else
65 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -070066 }
Yingdi Yu0c3e5912015-03-17 14:22:38 -070067 else
68 return false;
69 }
70
71
72 NonNegativeInteger childSeqMask = 1;
73 NonNegativeInteger childSeqNo = seqNo;
74 size_t childLevel = 0;
75 ndn::ConstBufferPtr childHash = hash;
76
77 NonNegativeInteger parentSeqMask = (~0) << 1;
78 NonNegativeInteger parentSeqNo = childSeqNo & parentSeqMask;
79 size_t parentLevel = 1;
80
81 Node::Index treePeakIndex(0, 0);
82 ConstSubTreeBinaryPtr subTree;
83
84 do { // get parent hash
85 Node::Index tmpIndex =
86 SubTreeBinary::toSubTreePeakIndex(Node::Index(childSeqNo, childLevel));
87
88 // std::cerr << "peak: " << tmpIndex.level << ", " << tmpIndex.seqNo << std::endl;
89 if (tmpIndex != treePeakIndex) {
90 treePeakIndex = tmpIndex;
91 auto it = trees.find(treePeakIndex);
92 if (it != trees.end() && it->second != nullptr) {
93 subTree = it->second;
94 }
95 else
96 return false;
97 }
98
99 // std::cerr << "Hey" << std::endl;
100 // right child or left child
101 ndn::util::Sha256 sha256;
102 if (childSeqMask & seqNo) { // right child
103 // std::cerr << "right" << std::endl;
104 // std::cerr << parentSeqNo << ", " << childLevel << std::endl;
105 auto leftChild = subTree->getNode(Node::Index(parentSeqNo, childLevel));
106 if (leftChild == nullptr && leftChild->getHash() == nullptr)
107 return false;
108
109 // std::cerr << "found node" << std::endl;
110 sha256 << parentLevel << parentSeqNo;
111 sha256.update(leftChild->getHash()->buf(), leftChild->getHash()->size());
112 sha256.update(childHash->buf(), childHash->size());
113 }
114 else { // left child
115 // std::cerr << "left" << std::endl;
116 ndn::ConstBufferPtr rightChildHash = Node::getEmptyHash();
117 if (rootNextSeqNo > childSeqNo + (1 << childLevel)) {
118 // std::cerr << childSeqNo + (1 << childLevel) << ", " << childLevel << std::endl;
119 auto rightChild = subTree->getNode(Node::Index(childSeqNo + (1 << childLevel), childLevel));
120 if (rightChild == nullptr || rightChild->getHash() == nullptr)
121 return false;
122 rightChildHash = rightChild->getHash();
123 // std::cerr << "left done" << std::endl;
124 }
125
126 sha256 << parentLevel << parentSeqNo;
127 sha256.update(childHash->buf(), childHash->size());
128 sha256.update(rightChildHash->buf(), rightChildHash->size());
129 }
130
131 childSeqMask = childSeqMask << 1;
132 childSeqNo = parentSeqNo;
133 childLevel = parentLevel;
134 childHash = sha256.computeDigest();
135
136 parentSeqMask = parentSeqMask << 1;
137 parentSeqNo = childSeqNo & parentSeqMask;
138 parentLevel++;
139
140 } while (childLevel < rootLevel);
141
142 // std::cerr << "done" << std::endl;
143
144 return (*childHash == *rootHash);
peizhen guo0401e3e2014-08-12 13:24:30 -0700145}
146
peizhen guo0401e3e2014-08-12 13:24:30 -0700147bool
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700148Auditor::isConsistent(const NonNegativeInteger& oldRootNextSeqNo,
149 ndn::ConstBufferPtr oldRootHash,
150 const NonNegativeInteger& newRootNextSeqNo,
151 ndn::ConstBufferPtr newRootHash,
152 const std::vector<shared_ptr<Data>>& proofs,
153 const Name& loggerName)
peizhen guo0401e3e2014-08-12 13:24:30 -0700154{
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700155 BOOST_ASSERT(oldRootHash != nullptr);
156 BOOST_ASSERT(newRootHash != nullptr);
peizhen guo0401e3e2014-08-12 13:24:30 -0700157
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700158 if (oldRootNextSeqNo > newRootNextSeqNo)
159 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700160
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700161 std::map<Node::Index, ConstSubTreeBinaryPtr> trees;
162 if (!loadProof(trees, proofs, loggerName))
163 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700164
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700165 // std::cerr << "1" << std::endl;
peizhen guo0401e3e2014-08-12 13:24:30 -0700166
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700167 // get boundary leaf:
168 NonNegativeInteger leafSeqNo = oldRootNextSeqNo - 1;
169 NonNegativeInteger treeSeqNo = leafSeqNo & ((~0) << (SubTreeBinary::SUB_TREE_DEPTH - 1));
170 auto it = trees.find(Node::Index(treeSeqNo, SubTreeBinary::SUB_TREE_DEPTH - 1));
171 if (it == trees.end())
172 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700173
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700174 auto leaf = it->second->getNode(Node::Index(leafSeqNo, 0));
175 if (leaf == nullptr || leaf->getHash() == nullptr)
176 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700177
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700178 if (!doesExist(leafSeqNo, leaf->getHash(), oldRootNextSeqNo, oldRootHash,
179 proofs, loggerName))
180 return false;
peizhen guo0401e3e2014-08-12 13:24:30 -0700181
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700182 // std::cerr << "2" << std::endl;
peizhen guo0401e3e2014-08-12 13:24:30 -0700183
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700184 if (oldRootNextSeqNo == newRootNextSeqNo) {
185 if (*oldRootHash == *newRootHash)
186 return true;
187 else
188 return false;
189 }
190
191 // std::cerr << "3" << std::endl;
192
193 if (!doesExist(leafSeqNo, leaf->getHash(), newRootNextSeqNo, newRootHash,
194 proofs, loggerName))
195 return false;
196
197 // std::cerr << "4" << std::endl;
198
199 return true;
peizhen guo0401e3e2014-08-12 13:24:30 -0700200}
201
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700202bool
203Auditor::loadProof(std::map<Node::Index, ConstSubTreeBinaryPtr>& trees,
204 const std::vector<shared_ptr<Data>>& proofs,
205 const Name& loggerName)
206{
207 try {
208 for (auto proof : proofs) {
209 // std::cerr << proof->getName() << std::endl;
210 auto subtree =
211 make_shared<SubTreeBinary>(loggerName,
212 [] (const Node::Index& idx) {},
213 [] (const Node::Index&,
214 const NonNegativeInteger& seqNo,
215 ndn::ConstBufferPtr hash) {});
216 subtree->decode(*proof);
217
218 // std::cerr << subtree->getPeakIndex().level << ", " << subtree->getPeakIndex().seqNo << std::endl;
219 if (trees.find(subtree->getPeakIndex()) == trees.end())
220 trees[subtree->getPeakIndex()] = subtree;
221 else
222 return false;
223 }
224 }
225 catch (SubTreeBinary::Error& e) {
226 // std::cerr << e.what() << std::endl;
227 return false;
228 }
229 catch (Node::Error& e) {
230 // std::cerr << e.what() << std::endl;
231 return false;
232 }
233 catch (tlv::Error&) {
234 return false;
235 }
236
237 return true;
238}
peizhen guo0401e3e2014-08-12 13:24:30 -0700239
240} // namespace nsl