blob: 4bc3d444aa9dab0942eaa0708fb40fb4b17ba8a5 [file] [log] [blame]
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento61a80032020-06-08 18:56:32 -04002/*
3 * Copyright (c) 2014-2020, Regents of the University of California
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -04004 *
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>
Davide Pesaventoc2649492020-12-22 21:43:35 -050024#include <ndn-cxx/util/exception.hpp>
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -040025
26namespace ndn {
27namespace nac {
28
29BOOST_CONCEPT_ASSERT((boost::EqualityComparable<EncryptedContent>));
30BOOST_CONCEPT_ASSERT((WireEncodable<EncryptedContent>));
31BOOST_CONCEPT_ASSERT((WireDecodable<EncryptedContent>));
32static_assert(std::is_base_of<ndn::tlv::Error, EncryptedContent::Error>::value,
33 "EncryptedContent::Error must inherit from tlv::Error");
34
35EncryptedContent::EncryptedContent(const Block& block)
36{
37 wireDecode(block);
38}
39
40EncryptedContent&
41EncryptedContent::setPayload(Block payload)
42{
43 m_wire.reset();
44 if (payload.type() != tlv::EncryptedPayload) {
45 m_payload = Block(tlv::EncryptedPayload, std::move(payload));
46 }
47 else {
48 m_payload = std::move(payload);
49 }
50 return *this;
51}
52
53EncryptedContent&
54EncryptedContent::setPayload(ConstBufferPtr payload)
55{
56 m_wire.reset();
57 m_payload = Block(tlv::EncryptedPayload, std::move(payload));
58 return *this;
59}
60
61EncryptedContent&
62EncryptedContent::setIv(Block iv)
63{
64 m_wire.reset();
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040065 if (iv.type() != tlv::InitializationVector) {
66 m_iv = Block(tlv::InitializationVector, std::move(iv));
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -040067 }
68 else {
69 m_iv = std::move(iv);
70 }
71 return *this;
72}
73
74EncryptedContent&
75EncryptedContent::setIv(ConstBufferPtr iv)
76{
77 m_wire.reset();
Alexander Afanasyev1a21e102018-06-13 20:33:21 -040078 m_iv = Block(tlv::InitializationVector, iv);
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -040079 return *this;
80}
81
82EncryptedContent&
83EncryptedContent::unsetIv()
84{
85 m_wire.reset();
86 m_iv = Block();
87 return *this;
88}
89
90EncryptedContent&
91EncryptedContent::setPayloadKey(Block key)
92{
93 m_wire.reset();
94 if (key.type() != tlv::EncryptedPayloadKey) {
95 m_payloadKey = Block(tlv::EncryptedPayloadKey, std::move(key));
96 }
97 else {
98 m_payloadKey = std::move(key);
99 }
100 return *this;
101}
102
103EncryptedContent&
104EncryptedContent::setPayloadKey(ConstBufferPtr key)
105{
106 m_wire.reset();
107 m_payloadKey = Block(tlv::EncryptedPayloadKey, std::move(key));
108 return *this;
109}
110
111EncryptedContent&
112EncryptedContent::unsetPayloadKey()
113{
114 m_wire.reset();
115 m_payloadKey = Block();
116 return *this;
117}
118
119EncryptedContent&
120EncryptedContent::setKeyLocator(Name keyLocator)
121{
122 m_wire.reset();
123 m_keyLocator = std::move(keyLocator);
124 return *this;
125}
126
127EncryptedContent&
128EncryptedContent::unsetKeyLocator()
129{
130 m_wire.reset();
131 m_keyLocator = Name();
132 return *this;
133}
134
135template<encoding::Tag TAG>
136size_t
137EncryptedContent::wireEncode(EncodingImpl<TAG>& block) const
138{
139 size_t totalLength = 0;
140
Davide Pesavento61a80032020-06-08 18:56:32 -0400141 if (hasKeyLocator()) {
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400142 totalLength += m_keyLocator.wireEncode(block);
143 }
144
Davide Pesavento61a80032020-06-08 18:56:32 -0400145 if (hasPayloadKey()) {
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400146 totalLength += block.prependBlock(m_payloadKey);
147 }
148
Davide Pesavento61a80032020-06-08 18:56:32 -0400149 if (hasIv()) {
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400150 totalLength += block.prependBlock(m_iv);
151 }
152
Davide Pesavento61a80032020-06-08 18:56:32 -0400153 if (m_payload.isValid()) {
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400154 totalLength += block.prependBlock(m_payload);
155 }
156 else {
Davide Pesaventoc2649492020-12-22 21:43:35 -0500157 NDN_THROW(Error("Required EncryptedPayload is not set on EncryptedContent"));
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400158 }
159
160 totalLength += block.prependVarNumber(totalLength);
161 totalLength += block.prependVarNumber(tlv::EncryptedContent);
162 return totalLength;
163}
164
165const Block&
166EncryptedContent::wireEncode() const
167{
168 if (m_wire.hasWire())
169 return m_wire;
170
171 EncodingEstimator estimator;
172 size_t estimatedSize = wireEncode(estimator);
173
174 EncodingBuffer buffer(estimatedSize, 0);
175 wireEncode(buffer);
176
177 m_wire = buffer.block();
178 return m_wire;
179}
180
181void
182EncryptedContent::wireDecode(const Block& wire)
183{
184 if (!wire.hasWire()) {
Davide Pesaventoc2649492020-12-22 21:43:35 -0500185 NDN_THROW(Error("The supplied block does not contain wire format"));
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400186 }
187
188 m_payload.reset();
189 m_iv.reset();
190 m_payloadKey.reset();
191
192 m_wire = wire;
193 m_wire.parse();
194
195 if (m_wire.type() != tlv::EncryptedContent) {
Davide Pesaventoc2649492020-12-22 21:43:35 -0500196 NDN_THROW(Error("Unexpected TLV type (expecting EncryptedContent, got " +
197 ndn::to_string(m_wire.type()) + ")"));
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400198 }
199
200 auto block = m_wire.find(tlv::EncryptedPayload);
201 if (block != m_wire.elements_end()) {
202 m_payload = *block;
203 }
204 else {
Davide Pesaventoc2649492020-12-22 21:43:35 -0500205 NDN_THROW(Error("Required EncryptedPayload not found in EncryptedContent"));
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400206 }
207
Alexander Afanasyev1a21e102018-06-13 20:33:21 -0400208 block = m_wire.find(tlv::InitializationVector);
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400209 if (block != m_wire.elements_end()) {
210 m_iv = *block;
211 }
212
213 block = m_wire.find(tlv::EncryptedPayloadKey);
214 if (block != m_wire.elements_end()) {
215 m_payloadKey = *block;
216 }
217
218 block = m_wire.find(tlv::Name);
219 if (block != m_wire.elements_end()) {
220 m_keyLocator.wireDecode(*block);
221 }
222}
223
224bool
225EncryptedContent::operator==(const EncryptedContent& rhs) const
226{
Davide Pesavento61a80032020-06-08 18:56:32 -0400227 return wireEncode() == rhs.wireEncode();
Alexander Afanasyev0db0feb2018-06-13 20:33:10 -0400228}
229
230} // namespace nac
231} // namespace ndn