blob: dfcb2602c8c82ed00be83b93aef45aae9f77537a [file] [log] [blame]
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhang19a11d22018-04-12 22:58:20 -07003 * Copyright (c) 2014-2018, Regents of the University of California
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08004 *
Zhiyi Zhang19a11d22018-04-12 22:58:20 -07005 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for
6 * NDN). See AUTHORS.md for complete list of ndn-group-encrypt authors and
7 * contributors.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08008 *
Zhiyi Zhang19a11d22018-04-12 22:58:20 -07009 * ndn-group-encrypt is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation, either version 3 of the License, or (at your option) any
12 * later version.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080013 *
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070014 * ndn-group-encrypt is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080018 *
19 * You should have received a copy of the GNU General Public License along with
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070020 * ndn-group-encrypt, e.g., in COPYING.md file. If not, see
21 * <http://www.gnu.org/licenses/>.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080022 *
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070023 * @author Zhiyi Zhang <zhiyi@cs.ucla.edu>
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080024 */
25
26#include "group-manager.hpp"
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080027#include "encrypted-content.hpp"
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070028#include "algo/encryptor.hpp"
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080029
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070030#include <iostream>
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080031#include <map>
32
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070033#include <ndn-cxx/util/string-helper.hpp>
34
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080035namespace ndn {
36namespace gep {
37
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070038GroupManager::GroupManager(const Name& prefix,
39 const Name& dataType,
40 const std::string& dbPath,
41 const int paramLength,
42 const int freshPeriod)
Yingdi Yu4467c112015-10-19 09:27:45 -070043 : m_namespace(prefix)
Yingdi Yu8c43fcc2016-03-09 18:23:57 -080044 , m_db(dbPath)
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080045 , m_paramLength(paramLength)
46 , m_freshPeriod(freshPeriod)
47{
Yingdi Yu3decf4e2015-11-02 12:33:31 -080048 m_namespace.append(NAME_COMPONENT_READ).append(dataType);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080049}
50
51std::list<Data>
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -070052GroupManager::getGroupKey(const TimeStamp& timeslot, bool needRegenerate)
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080053{
54 std::map<Name, Buffer> memberKeys;
55 std::list<Data> result;
56
57 // get time interval
58 Interval finalInterval = calculateInterval(timeslot, memberKeys);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070059 if (finalInterval.isValid() == false) {
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080060 return result;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070061 }
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080062
63 std::string startTs = boost::posix_time::to_iso_string(finalInterval.getStartTime());
64 std::string endTs = boost::posix_time::to_iso_string(finalInterval.getEndTime());
65
66 // generate the pri key and pub key
67 Buffer priKeyBuf, pubKeyBuf;
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -070068 Name eKeyName(m_namespace);
69 eKeyName.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
70
71 if (!needRegenerate && m_db.hasEKey(eKeyName)) {
72 std::tie(pubKeyBuf, priKeyBuf) = getEKey(eKeyName);
73 }
74 else {
75 generateKeyPairs(priKeyBuf, pubKeyBuf);
76 if (m_db.hasEKey(eKeyName)) {
77 deleteEKey(eKeyName);
78 }
79 addEKey(eKeyName, pubKeyBuf, priKeyBuf);
80 }
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080081
82 // add the first element to the result
83 // E-KEY (public key) data packet name convention:
84 // /<data_type>/E-KEY/[start-ts]/[end-ts]
85 Data data = createEKeyData(startTs, endTs, pubKeyBuf);
86 result.push_back(data);
87
88 // encrypt pri key with pub key from certificate
89 for (const auto& entry : memberKeys) {
90 const Name& keyName = entry.first;
91 const Buffer& certKey = entry.second;
92
93 // generate the name of the packet
94 // D-KEY (private key) data packet name convention:
95 // /<data_type>/D-KEY/[start-ts]/[end-ts]/[member-name]
96 data = createDKeyData(startTs, endTs, keyName, priKeyBuf, certKey);
97 result.push_back(data);
98 }
99 return result;
100}
101
102void
103GroupManager::addSchedule(const std::string& scheduleName, const Schedule& schedule)
104{
105 m_db.addSchedule(scheduleName, schedule);
106}
107
108void
109GroupManager::deleteSchedule(const std::string& scheduleName)
110{
111 m_db.deleteSchedule(scheduleName);
112}
113
114void
115GroupManager::updateSchedule(const std::string& scheduleName, const Schedule& schedule)
116{
117 m_db.updateSchedule(scheduleName, schedule);
118}
119
120void
121GroupManager::addMember(const std::string& scheduleName, const Data& memCert)
122{
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700123 security::v2::Certificate cert(memCert);
124 Buffer keybits = cert.getPublicKey();
125 m_db.addMember(scheduleName, cert.getKeyName(), keybits);
126}
127
128void
129GroupManager::addMember(const std::string& scheduleName, const Name& keyName, const Buffer& key)
130{
131 m_db.addMember(scheduleName, keyName, key);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800132}
133
134void
135GroupManager::removeMember(const Name& identity)
136{
137 m_db.deleteMember(identity);
138}
139
140void
141GroupManager::updateMemberSchedule(const Name& identity, const std::string& scheduleName)
142{
143 m_db.updateMemberSchedule(identity, scheduleName);
144}
145
146Interval
147GroupManager::calculateInterval(const TimeStamp& timeslot, std::map<Name, Buffer>& memberKeys)
148{
149 // prepare
150 Interval positiveResult;
151 Interval negativeResult;
152 Interval tempInterval;
153 Interval finalInterval;
154 bool isPositive;
155 memberKeys.clear();
156
157 // get the all intervals from schedules
158 for (const std::string& scheduleName : m_db.listAllScheduleNames()) {
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800159 const Schedule& schedule = m_db.getSchedule(scheduleName);
160 std::tie(isPositive, tempInterval) = schedule.getCoveringInterval(timeslot);
161
162 if (isPositive) {
163 if (!positiveResult.isValid())
164 positiveResult = tempInterval;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700165 positiveResult&& tempInterval;
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800166
167 std::map<Name, Buffer> m = m_db.getScheduleMembers(scheduleName);
168 memberKeys.insert(m.begin(), m.end());
169 }
170 else {
171 if (!negativeResult.isValid())
172 negativeResult = tempInterval;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700173 negativeResult&& tempInterval;
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800174 }
175 }
176 if (!positiveResult.isValid()) {
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700177 // return invalid interval when there is no member has interval covering the
178 // time slot
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800179 return Interval(false);
180 }
181
182 // get the final interval result
183 if (negativeResult.isValid())
184 finalInterval = positiveResult && negativeResult;
185 else
186 finalInterval = positiveResult;
187
188 return finalInterval;
189}
190
191void
192GroupManager::generateKeyPairs(Buffer& priKeyBuf, Buffer& pubKeyBuf) const
193{
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800194 RsaKeyParams params(m_paramLength);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700195 DecryptKey<algo::Rsa> privateKey = algo::Rsa::generateKey(params);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800196 priKeyBuf = privateKey.getKeyBits();
197 EncryptKey<algo::Rsa> publicKey = algo::Rsa::deriveEncryptKey(priKeyBuf);
198 pubKeyBuf = publicKey.getKeyBits();
199}
200
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800201Data
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700202GroupManager::createEKeyData(const std::string& startTs,
203 const std::string& endTs,
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800204 const Buffer& pubKeyBuf)
205{
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800206 Name name(m_namespace);
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800207 name.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800208 Data data(name);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800209 data.setFreshnessPeriod(time::hours(m_freshPeriod));
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700210 data.setContent(pubKeyBuf.data(), pubKeyBuf.size());
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800211 m_keyChain.sign(data);
212 return data;
213}
214
215Data
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700216GroupManager::createDKeyData(const std::string& startTs,
217 const std::string& endTs,
218 const Name& keyName,
219 const Buffer& priKeyBuf,
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800220 const Buffer& certKey)
221{
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800222 Name name(m_namespace);
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800223 name.append(NAME_COMPONENT_D_KEY);
224 name.append(startTs).append(endTs);
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800225 Data data = Data(name);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800226 data.setFreshnessPeriod(time::hours(m_freshPeriod));
Yingdi Yu883f4202015-11-02 13:54:11 -0800227 algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700228 algo::encryptData(data,
229 priKeyBuf.data(),
230 priKeyBuf.size(),
231 keyName,
232 certKey.data(),
233 certKey.size(),
234 eparams);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800235 m_keyChain.sign(data);
236 return data;
237}
238
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -0700239void
240GroupManager::addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey)
241{
242 m_db.addEKey(eKeyName, pubKey, priKey);
243}
244
245std::tuple<Buffer, Buffer>
246GroupManager::getEKey(const Name& eKeyName)
247{
248 return m_db.getEKey(eKeyName);
249}
250
251void
252GroupManager::deleteEKey(const Name& eKeyName)
253{
254 m_db.deleteEKey(eKeyName);
255}
256
257void
258GroupManager::cleanEKeys()
259{
260 m_db.cleanEKeys();
261}
262
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700263} // namespace gep
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800264} // namespace ndn