blob: bd5feb0f0f8eb6621dfa7c45f5d3b6c34c61593b [file] [log] [blame]
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Regents of the University of California
4 *
5 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
6 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
7 *
8 * ndn-group-encrypt 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 * ndn-group-encrypt 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 * ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
20 */
21
22#include "group-manager.hpp"
Yingdi Yu3decf4e2015-11-02 12:33:31 -080023#include "algo/encryptor.hpp"
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080024#include "encrypted-content.hpp"
25
26#include <map>
27
28namespace ndn {
29namespace gep {
30
Yingdi Yu8c43fcc2016-03-09 18:23:57 -080031GroupManager::GroupManager(const Name& prefix, const Name& dataType, const std::string& dbPath,
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080032 const int paramLength, const int freshPeriod)
Yingdi Yu4467c112015-10-19 09:27:45 -070033 : m_namespace(prefix)
Yingdi Yu8c43fcc2016-03-09 18:23:57 -080034 , m_db(dbPath)
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080035 , m_paramLength(paramLength)
36 , m_freshPeriod(freshPeriod)
37{
Yingdi Yu3decf4e2015-11-02 12:33:31 -080038 m_namespace.append(NAME_COMPONENT_READ).append(dataType);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080039}
40
41std::list<Data>
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -070042GroupManager::getGroupKey(const TimeStamp& timeslot, bool needRegenerate)
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080043{
44 std::map<Name, Buffer> memberKeys;
45 std::list<Data> result;
46
47 // get time interval
48 Interval finalInterval = calculateInterval(timeslot, memberKeys);
49 if (finalInterval.isValid() == false)
50 return result;
51
52 std::string startTs = boost::posix_time::to_iso_string(finalInterval.getStartTime());
53 std::string endTs = boost::posix_time::to_iso_string(finalInterval.getEndTime());
54
55 // generate the pri key and pub key
56 Buffer priKeyBuf, pubKeyBuf;
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -070057 Name eKeyName(m_namespace);
58 eKeyName.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
59
60 if (!needRegenerate && m_db.hasEKey(eKeyName)) {
61 std::tie(pubKeyBuf, priKeyBuf) = getEKey(eKeyName);
62 }
63 else {
64 generateKeyPairs(priKeyBuf, pubKeyBuf);
65 if (m_db.hasEKey(eKeyName)) {
66 deleteEKey(eKeyName);
67 }
68 addEKey(eKeyName, pubKeyBuf, priKeyBuf);
69 }
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080070
71 // add the first element to the result
72 // E-KEY (public key) data packet name convention:
73 // /<data_type>/E-KEY/[start-ts]/[end-ts]
74 Data data = createEKeyData(startTs, endTs, pubKeyBuf);
75 result.push_back(data);
76
77 // encrypt pri key with pub key from certificate
78 for (const auto& entry : memberKeys) {
79 const Name& keyName = entry.first;
80 const Buffer& certKey = entry.second;
81
82 // generate the name of the packet
83 // D-KEY (private key) data packet name convention:
84 // /<data_type>/D-KEY/[start-ts]/[end-ts]/[member-name]
85 data = createDKeyData(startTs, endTs, keyName, priKeyBuf, certKey);
86 result.push_back(data);
87 }
88 return result;
89}
90
91void
92GroupManager::addSchedule(const std::string& scheduleName, const Schedule& schedule)
93{
94 m_db.addSchedule(scheduleName, schedule);
95}
96
97void
98GroupManager::deleteSchedule(const std::string& scheduleName)
99{
100 m_db.deleteSchedule(scheduleName);
101}
102
103void
104GroupManager::updateSchedule(const std::string& scheduleName, const Schedule& schedule)
105{
106 m_db.updateSchedule(scheduleName, schedule);
107}
108
109void
110GroupManager::addMember(const std::string& scheduleName, const Data& memCert)
111{
112 IdentityCertificate cert(memCert);
113 m_db.addMember(scheduleName, cert.getPublicKeyName(), cert.getPublicKeyInfo().get());
114}
115
116void
117GroupManager::removeMember(const Name& identity)
118{
119 m_db.deleteMember(identity);
120}
121
122void
123GroupManager::updateMemberSchedule(const Name& identity, const std::string& scheduleName)
124{
125 m_db.updateMemberSchedule(identity, scheduleName);
126}
127
128Interval
129GroupManager::calculateInterval(const TimeStamp& timeslot, std::map<Name, Buffer>& memberKeys)
130{
131 // prepare
132 Interval positiveResult;
133 Interval negativeResult;
134 Interval tempInterval;
135 Interval finalInterval;
136 bool isPositive;
137 memberKeys.clear();
138
139 // get the all intervals from schedules
140 for (const std::string& scheduleName : m_db.listAllScheduleNames()) {
141
142 const Schedule& schedule = m_db.getSchedule(scheduleName);
143 std::tie(isPositive, tempInterval) = schedule.getCoveringInterval(timeslot);
144
145 if (isPositive) {
146 if (!positiveResult.isValid())
147 positiveResult = tempInterval;
148 positiveResult && tempInterval;
149
150 std::map<Name, Buffer> m = m_db.getScheduleMembers(scheduleName);
151 memberKeys.insert(m.begin(), m.end());
152 }
153 else {
154 if (!negativeResult.isValid())
155 negativeResult = tempInterval;
156 negativeResult && tempInterval;
157 }
158 }
159 if (!positiveResult.isValid()) {
160 // return invalid interval when there is no member has interval covering the time slot
161 return Interval(false);
162 }
163
164 // get the final interval result
165 if (negativeResult.isValid())
166 finalInterval = positiveResult && negativeResult;
167 else
168 finalInterval = positiveResult;
169
170 return finalInterval;
171}
172
173void
174GroupManager::generateKeyPairs(Buffer& priKeyBuf, Buffer& pubKeyBuf) const
175{
176 RandomNumberGenerator rng;
177 RsaKeyParams params(m_paramLength);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800178 DecryptKey<algo::Rsa> privateKey = algo::Rsa::generateKey(rng, params);
179 priKeyBuf = privateKey.getKeyBits();
180 EncryptKey<algo::Rsa> publicKey = algo::Rsa::deriveEncryptKey(priKeyBuf);
181 pubKeyBuf = publicKey.getKeyBits();
182}
183
184
185Data
186GroupManager::createEKeyData(const std::string& startTs, const std::string& endTs,
187 const Buffer& pubKeyBuf)
188{
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800189 Name name(m_namespace);
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800190 name.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800191 Data data(name);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800192 data.setFreshnessPeriod(time::hours(m_freshPeriod));
193 data.setContent(pubKeyBuf.get(), pubKeyBuf.size());
194 m_keyChain.sign(data);
195 return data;
196}
197
198Data
199GroupManager::createDKeyData(const std::string& startTs, const std::string& endTs,
200 const Name& keyName, const Buffer& priKeyBuf,
201 const Buffer& certKey)
202{
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800203 Name name(m_namespace);
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800204 name.append(NAME_COMPONENT_D_KEY);
205 name.append(startTs).append(endTs);
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800206 Data data = Data(name);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800207 data.setFreshnessPeriod(time::hours(m_freshPeriod));
Yingdi Yu883f4202015-11-02 13:54:11 -0800208 algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800209 algo::encryptData(data, priKeyBuf.buf(), priKeyBuf.size(), keyName,
210 certKey.buf(), certKey.size(), eparams);
211 m_keyChain.sign(data);
212 return data;
213}
214
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -0700215void
216GroupManager::addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey)
217{
218 m_db.addEKey(eKeyName, pubKey, priKey);
219}
220
221std::tuple<Buffer, Buffer>
222GroupManager::getEKey(const Name& eKeyName)
223{
224 return m_db.getEKey(eKeyName);
225}
226
227void
228GroupManager::deleteEKey(const Name& eKeyName)
229{
230 m_db.deleteEKey(eKeyName);
231}
232
233void
234GroupManager::cleanEKeys()
235{
236 m_db.cleanEKeys();
237}
238
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800239} // namespace ndn
240} // namespace ndn