blob: 1046b1594c6c203fab07ebc0faef44319db5e6d8 [file] [log] [blame]
peizhen guocf4df2d2014-08-12 13:22:32 -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 guocf4df2d2014-08-12 13:22:32 -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 guocf4df2d2014-08-12 13:22:32 -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 guocf4df2d2014-08-12 13:22:32 -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 guocf4df2d2014-08-12 13:22:32 -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 guocf4df2d2014-08-12 13:22:32 -070020 */
Yingdi Yu0c3e5912015-03-17 14:22:38 -070021
peizhen guocf4df2d2014-08-12 13:22:32 -070022#include "leaf.hpp"
Yingdi Yu0c3e5912015-03-17 14:22:38 -070023#include "tlv.hpp"
24#include <ndn-cxx/security/digest-sha256.hpp>
25#include <ndn-cxx/encoding/block-helpers.hpp>
26#include <ndn-cxx/util/crypto.hpp>
peizhen guocf4df2d2014-08-12 13:22:32 -070027
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -070028namespace ndn {
29namespace delorean {
peizhen guocf4df2d2014-08-12 13:22:32 -070030
Yingdi Yu0c3e5912015-03-17 14:22:38 -070031const Name Leaf::EMPTY_NAME;
32const size_t Leaf::N_LOGGER_LEAF_SUFFIX = 4;
33const ssize_t Leaf::OFFSET_LEAF_SEQNO = -2;
34const ssize_t Leaf::OFFSET_LEAF_HASH = -1;
35
36Leaf::Leaf()
peizhen guocf4df2d2014-08-12 13:22:32 -070037{
peizhen guocf4df2d2014-08-12 13:22:32 -070038}
39
Yingdi Yu0c3e5912015-03-17 14:22:38 -070040Leaf::Leaf(const Name& dataName,
41 const Timestamp& timestamp,
42 const NonNegativeInteger& dataSeqNo,
43 const NonNegativeInteger& signerSeqNo,
44 const Name& loggerName)
45 : m_dataName(dataName)
46 , m_timestamp(timestamp)
47 , m_dataSeqNo(dataSeqNo)
48 , m_signerSeqNo(signerSeqNo)
49 , m_loggerName(loggerName)
50{
51 if (m_dataSeqNo < m_signerSeqNo)
52 throw Error("Leaf: signer seqNo should be less than the data seqNo");
53}
peizhen guocf4df2d2014-08-12 13:22:32 -070054
55void
Yingdi Yu0c3e5912015-03-17 14:22:38 -070056Leaf::setDataSeqNo(const NonNegativeInteger& dataSeqNo)
peizhen guocf4df2d2014-08-12 13:22:32 -070057{
Yingdi Yu0c3e5912015-03-17 14:22:38 -070058 if (dataSeqNo < m_signerSeqNo)
59 throw Error("Leaf: signer seqNo should be less than the data seqNo");
60
61 m_wire.reset();
62 m_dataSeqNo = dataSeqNo;
63}
64
65void
66Leaf::setDataName(const Name& dataName)
67{
68 m_wire.reset();
69 m_dataName = dataName;
70}
71
72void
73Leaf::setTimestamp(const Timestamp& timestamp)
74{
75 m_wire.reset();
76 m_timestamp = timestamp;
77}
78
79void
80Leaf::setSignerSeqNo(const NonNegativeInteger& signerSeqNo)
81{
82 if (m_dataSeqNo < signerSeqNo)
83 throw Error("Leaf: signer seqNo should be less than the data seqNo");
84
85 m_wire.reset();
86 m_signerSeqNo = signerSeqNo;
87}
88
89void
90Leaf::setLoggerName(const Name& loggerName)
91{
92 m_loggerName = loggerName;
93}
94
95ndn::ConstBufferPtr
96Leaf::getHash() const
97{
98 wireEncode();
99 return ndn::crypto::sha256(m_wire.wire(), m_wire.size());
100}
101
102shared_ptr<Data>
103Leaf::encode() const
104{
105 auto data = make_shared<Data>();
106
107 ndn::ConstBufferPtr hash = getHash();
108
109 // Name
110 Name dataName = m_loggerName;
111 dataName.appendNumber(m_dataSeqNo).append(hash->buf(), hash->size());
112 data->setName(dataName);
113
114 // Content
115 data->setContent(wireEncode());
116
117 // Signature
118 ndn::DigestSha256 sig;
119 data->setSignature(sig);
120
121 Block sigValue(tlv::SignatureValue,
122 ndn::crypto::sha256(data->wireEncode().value(),
123 data->wireEncode().value_size() -
124 data->getSignature().getValue().size()));
125 data->setSignatureValue(sigValue);
126
127 data->wireEncode();
128
129 return data;
130}
131
132void
133Leaf::decode(const Data& data)
134{
135 const Name& dataName = data.getName();
136
137 if (!m_loggerName.isPrefixOf(dataName))
138 throw Error("decode: leaf data name does not match logger name");
139
140 if (m_loggerName.size() + N_LOGGER_LEAF_SUFFIX != dataName.size())
141 throw Error("decode: leaf data name does not follow the naming convention");
142
143 ndn::ConstBufferPtr leafHash;
144 NonNegativeInteger dataSeqNo;
145 try {
146 leafHash = make_shared<ndn::Buffer>(dataName.get(OFFSET_LEAF_HASH).value(),
147 dataName.get(OFFSET_LEAF_HASH).value_size());
148
149 dataSeqNo = dataName.get(OFFSET_LEAF_SEQNO).toNumber();
150 }
151 catch (tlv::Error&) {
152 throw Error("decode: logger name encoding error");
153 }
154
155 wireDecode(data.getContent().blockFromValue());
156
157 if (*leafHash != *getHash())
158 throw Error("decode: inconsistent hash");
159
160 if (m_dataSeqNo != dataSeqNo)
161 throw Error("decode: seqNo does not match");
162}
163
164template<ndn::encoding::Tag TAG>
165size_t
166Leaf::wireEncode(ndn::EncodingImpl<TAG>& block) const
167{
168 size_t totalLength = 0;
169
Alexander Afanasyevb1ba9c92017-05-06 13:16:18 -0700170 totalLength += prependNonNegativeIntegerBlock(block, tlv::SignerSeqNo, m_signerSeqNo);
171 totalLength += prependNonNegativeIntegerBlock(block, tlv::DataSeqNo, m_dataSeqNo);
172 totalLength += prependNonNegativeIntegerBlock(block, tlv::Timestamp, m_timestamp);
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700173 totalLength += m_dataName.wireEncode(block);
174
175 totalLength += block.prependVarNumber(totalLength);
176 totalLength += block.prependVarNumber(tlv::LoggerLeaf);
177
178 return totalLength;
179}
180
181template size_t
182Leaf::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>&) const;
183
184template size_t
185Leaf::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>&) const;
186
187
188const Block&
189Leaf::wireEncode() const
190{
191 if (m_wire.hasWire())
192 return m_wire;
193
194 ndn::EncodingEstimator estimator;
195 size_t estimatedSize = wireEncode(estimator);
196
197 ndn::EncodingBuffer buffer(estimatedSize, 0);
198 wireEncode(buffer);
199
200 m_wire = buffer.block();
201 return m_wire;
202}
203
204void
205Leaf::wireDecode(const Block& wire)
206{
207 if (!wire.hasWire()) {
208 throw Error("The supplied block does not contain wire format");
209 }
210
211 m_wire = wire;
212 m_wire.parse();
213
214 if (m_wire.type() != tlv::LoggerLeaf)
215 throw tlv::Error("Unexpected TLV type when decoding logger leaf");
216
217 Block::element_const_iterator it = m_wire.elements_begin();
218
219 // the first block must be dataName
220 if (it != m_wire.elements_end() && it->type() == tlv::Name) {
221 m_dataName.wireDecode(*it);
222 it++;
223 }
224 else
225 throw Error("The first sub-TLV is not Name");
226
227 // the second block must be timestamp
228 if (it != m_wire.elements_end() && it->type() == tlv::Timestamp) {
229 m_timestamp = readNonNegativeInteger(*it);
230 it++;
231 }
232 else
233 throw Error("The second sub-TLV is not Timestamp");
234
235 // the third block must be DataSeqNo
236 if (it != m_wire.elements_end() && it->type() == tlv::DataSeqNo) {
237 m_dataSeqNo = readNonNegativeInteger(*it);
238 it++;
239 }
240 else
241 throw Error("The third sub-TLV is not DataSeqNo");
242
243 // the third block must be SignerSeqNo
244 if (it != m_wire.elements_end() && it->type() == tlv::SignerSeqNo) {
245 m_signerSeqNo = readNonNegativeInteger(*it);
246 it++;
247 }
248 else
249 throw Error("The fourth sub-TLV is not SignerSeqNo");
250
251 if (it != m_wire.elements_end())
252 throw Error("No more sub-TLV in LoggerLeaf");
peizhen guocf4df2d2014-08-12 13:22:32 -0700253}
254
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -0700255} // namespace delorean
256} // namespace ndn