blob: f9738bdf02a12a359c273d1647bf6a8b628251d6 [file] [log] [blame]
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2018, Regents of the University of California
4 *
5 * NAC library is free software: you can redistribute it and/or modify it under the
6 * terms of the GNU Lesser General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option) any later version.
8 *
9 * NAC library is distributed in the hope that it will be useful, but WITHOUT ANY
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
12 *
13 * You should have received copies of the GNU General Public License and GNU Lesser
14 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 * See AUTHORS.md for complete list of NAC library authors and contributors.
18 */
19
20#include "encrypted-content.hpp"
21
22#include <ndn-cxx/encoding/block-helpers.hpp>
23#include <ndn-cxx/util/concepts.hpp>
24
25namespace ndn {
26namespace nac {
27
28BOOST_CONCEPT_ASSERT((boost::EqualityComparable<EncryptedContent>));
29BOOST_CONCEPT_ASSERT((WireEncodable<EncryptedContent>));
30BOOST_CONCEPT_ASSERT((WireDecodable<EncryptedContent>));
31static_assert(std::is_base_of<ndn::tlv::Error, EncryptedContent::Error>::value,
32 "EncryptedContent::Error must inherit from tlv::Error");
33
34EncryptedContent::EncryptedContent(const Block& block)
35{
36 wireDecode(block);
37}
38
39EncryptedContent&
40EncryptedContent::setPayload(Block payload)
41{
42 m_wire.reset();
43 if (payload.type() != tlv::EncryptedPayload) {
44 m_payload = Block(tlv::EncryptedPayload, std::move(payload));
45 }
46 else {
47 m_payload = std::move(payload);
48 }
49 return *this;
50}
51
52EncryptedContent&
53EncryptedContent::setPayload(ConstBufferPtr payload)
54{
55 m_wire.reset();
56 m_payload = Block(tlv::EncryptedPayload, std::move(payload));
57 return *this;
58}
59
60EncryptedContent&
61EncryptedContent::setIv(Block iv)
62{
63 m_wire.reset();
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040064 if (iv.type() != tlv::InitializationVector) {
65 m_iv = Block(tlv::InitializationVector, std::move(iv));
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -040066 }
67 else {
68 m_iv = std::move(iv);
69 }
70 return *this;
71}
72
73EncryptedContent&
74EncryptedContent::setIv(ConstBufferPtr iv)
75{
76 m_wire.reset();
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040077 m_iv = Block(tlv::InitializationVector, iv);
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -040078 return *this;
79}
80
81EncryptedContent&
82EncryptedContent::unsetIv()
83{
84 m_wire.reset();
85 m_iv = Block();
86 return *this;
87}
88
89EncryptedContent&
90EncryptedContent::setPayloadKey(Block key)
91{
92 m_wire.reset();
93 if (key.type() != tlv::EncryptedPayloadKey) {
94 m_payloadKey = Block(tlv::EncryptedPayloadKey, std::move(key));
95 }
96 else {
97 m_payloadKey = std::move(key);
98 }
99 return *this;
100}
101
102EncryptedContent&
103EncryptedContent::setPayloadKey(ConstBufferPtr key)
104{
105 m_wire.reset();
106 m_payloadKey = Block(tlv::EncryptedPayloadKey, std::move(key));
107 return *this;
108}
109
110EncryptedContent&
111EncryptedContent::unsetPayloadKey()
112{
113 m_wire.reset();
114 m_payloadKey = Block();
115 return *this;
116}
117
118EncryptedContent&
119EncryptedContent::setKeyLocator(Name keyLocator)
120{
121 m_wire.reset();
122 m_keyLocator = std::move(keyLocator);
123 return *this;
124}
125
126EncryptedContent&
127EncryptedContent::unsetKeyLocator()
128{
129 m_wire.reset();
130 m_keyLocator = Name();
131 return *this;
132}
133
134template<encoding::Tag TAG>
135size_t
136EncryptedContent::wireEncode(EncodingImpl<TAG>& block) const
137{
138 size_t totalLength = 0;
139
140 if (!m_keyLocator.empty()) {
141 totalLength += m_keyLocator.wireEncode(block);
142 }
143
144 if (!m_payloadKey.empty()) {
145 totalLength += block.prependBlock(m_payloadKey);
146 }
147
148 if (!m_iv.empty()) {
149 totalLength += block.prependBlock(m_iv);
150 }
151
152 if (!m_payload.empty()) {
153 totalLength += block.prependBlock(m_payload);
154 }
155 else {
156 BOOST_THROW_EXCEPTION(Error("Required EncryptedPayload is not set on EncryptedContent"));
157 }
158
159 totalLength += block.prependVarNumber(totalLength);
160 totalLength += block.prependVarNumber(tlv::EncryptedContent);
161 return totalLength;
162}
163
164const Block&
165EncryptedContent::wireEncode() const
166{
167 if (m_wire.hasWire())
168 return m_wire;
169
170 EncodingEstimator estimator;
171 size_t estimatedSize = wireEncode(estimator);
172
173 EncodingBuffer buffer(estimatedSize, 0);
174 wireEncode(buffer);
175
176 m_wire = buffer.block();
177 return m_wire;
178}
179
180void
181EncryptedContent::wireDecode(const Block& wire)
182{
183 if (!wire.hasWire()) {
184 BOOST_THROW_EXCEPTION(Error("The supplied block does not contain wire format"));
185 }
186
187 m_payload.reset();
188 m_iv.reset();
189 m_payloadKey.reset();
190
191 m_wire = wire;
192 m_wire.parse();
193
194 if (m_wire.type() != tlv::EncryptedContent) {
195 BOOST_THROW_EXCEPTION(Error("Unexpected TLV type (expecting EncryptedContent, got" +
196 ndn::to_string(m_wire.type()) + ")"));
197 }
198
199 auto block = m_wire.find(tlv::EncryptedPayload);
200 if (block != m_wire.elements_end()) {
201 m_payload = *block;
202 }
203 else {
204 BOOST_THROW_EXCEPTION(Error("Required EncryptedPayload not found in EncryptedContent"));
205 }
206
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400207 block = m_wire.find(tlv::InitializationVector);
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400208 if (block != m_wire.elements_end()) {
209 m_iv = *block;
210 }
211
212 block = m_wire.find(tlv::EncryptedPayloadKey);
213 if (block != m_wire.elements_end()) {
214 m_payloadKey = *block;
215 }
216
217 block = m_wire.find(tlv::Name);
218 if (block != m_wire.elements_end()) {
219 m_keyLocator.wireDecode(*block);
220 }
221}
222
223bool
224EncryptedContent::operator==(const EncryptedContent& rhs) const
225{
226 return (wireEncode() == rhs.wireEncode());
227}
228
229} // namespace nac
230} // namespace ndn