blob: 0521dffc15487503b22f4fdc8c9f161911b499bc [file] [log] [blame]
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9091d832018-04-18 17:21:08 -04003 * Copyright (c) 2014-2018, Regents of the University of California
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08004 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -04005 * This file is part of NAC (Name-Based Access Control for NDN).
6 * See AUTHORS.md for complete list of NAC authors and contributors.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08007 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -04008 * NAC 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.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080011 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -040012 * NAC 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.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080015 *
16 * You should have received a copy of the GNU General Public License along with
Alexander Afanasyev9091d832018-04-18 17:21:08 -040017 * NAC, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080018 *
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070019 * @author Zhiyi Zhang <zhiyi@cs.ucla.edu>
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080020 */
21
22#include "group-manager.hpp"
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080023#include "encrypted-content.hpp"
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070024#include "algo/encryptor.hpp"
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080025
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070026#include <iostream>
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080027#include <map>
28
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070029#include <ndn-cxx/util/string-helper.hpp>
30
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080031namespace ndn {
Alexander Afanasyev9091d832018-04-18 17:21:08 -040032namespace nac {
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080033
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070034GroupManager::GroupManager(const Name& prefix,
35 const Name& dataType,
36 const std::string& dbPath,
37 const int paramLength,
38 const int freshPeriod)
Yingdi Yu4467c112015-10-19 09:27:45 -070039 : m_namespace(prefix)
Yingdi Yu8c43fcc2016-03-09 18:23:57 -080040 , m_db(dbPath)
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080041 , m_paramLength(paramLength)
42 , m_freshPeriod(freshPeriod)
43{
Yingdi Yu3decf4e2015-11-02 12:33:31 -080044 m_namespace.append(NAME_COMPONENT_READ).append(dataType);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080045}
46
47std::list<Data>
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -070048GroupManager::getGroupKey(const TimeStamp& timeslot, bool needRegenerate)
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080049{
50 std::map<Name, Buffer> memberKeys;
51 std::list<Data> result;
52
53 // get time interval
54 Interval finalInterval = calculateInterval(timeslot, memberKeys);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070055 if (finalInterval.isValid() == false) {
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080056 return result;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070057 }
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080058
59 std::string startTs = boost::posix_time::to_iso_string(finalInterval.getStartTime());
60 std::string endTs = boost::posix_time::to_iso_string(finalInterval.getEndTime());
61
62 // generate the pri key and pub key
63 Buffer priKeyBuf, pubKeyBuf;
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -070064 Name eKeyName(m_namespace);
65 eKeyName.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
66
67 if (!needRegenerate && m_db.hasEKey(eKeyName)) {
68 std::tie(pubKeyBuf, priKeyBuf) = getEKey(eKeyName);
69 }
70 else {
71 generateKeyPairs(priKeyBuf, pubKeyBuf);
72 if (m_db.hasEKey(eKeyName)) {
73 deleteEKey(eKeyName);
74 }
75 addEKey(eKeyName, pubKeyBuf, priKeyBuf);
76 }
Zhiyi Zhang84986cc2015-09-21 00:26:07 +080077
78 // add the first element to the result
79 // E-KEY (public key) data packet name convention:
80 // /<data_type>/E-KEY/[start-ts]/[end-ts]
81 Data data = createEKeyData(startTs, endTs, pubKeyBuf);
82 result.push_back(data);
83
84 // encrypt pri key with pub key from certificate
85 for (const auto& entry : memberKeys) {
86 const Name& keyName = entry.first;
87 const Buffer& certKey = entry.second;
88
89 // generate the name of the packet
90 // D-KEY (private key) data packet name convention:
91 // /<data_type>/D-KEY/[start-ts]/[end-ts]/[member-name]
92 data = createDKeyData(startTs, endTs, keyName, priKeyBuf, certKey);
93 result.push_back(data);
94 }
95 return result;
96}
97
98void
99GroupManager::addSchedule(const std::string& scheduleName, const Schedule& schedule)
100{
101 m_db.addSchedule(scheduleName, schedule);
102}
103
104void
105GroupManager::deleteSchedule(const std::string& scheduleName)
106{
107 m_db.deleteSchedule(scheduleName);
108}
109
110void
111GroupManager::updateSchedule(const std::string& scheduleName, const Schedule& schedule)
112{
113 m_db.updateSchedule(scheduleName, schedule);
114}
115
116void
117GroupManager::addMember(const std::string& scheduleName, const Data& memCert)
118{
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700119 security::v2::Certificate cert(memCert);
120 Buffer keybits = cert.getPublicKey();
121 m_db.addMember(scheduleName, cert.getKeyName(), keybits);
122}
123
124void
125GroupManager::addMember(const std::string& scheduleName, const Name& keyName, const Buffer& key)
126{
127 m_db.addMember(scheduleName, keyName, key);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800128}
129
130void
131GroupManager::removeMember(const Name& identity)
132{
133 m_db.deleteMember(identity);
134}
135
136void
137GroupManager::updateMemberSchedule(const Name& identity, const std::string& scheduleName)
138{
139 m_db.updateMemberSchedule(identity, scheduleName);
140}
141
142Interval
143GroupManager::calculateInterval(const TimeStamp& timeslot, std::map<Name, Buffer>& memberKeys)
144{
145 // prepare
146 Interval positiveResult;
147 Interval negativeResult;
148 Interval tempInterval;
149 Interval finalInterval;
150 bool isPositive;
151 memberKeys.clear();
152
153 // get the all intervals from schedules
154 for (const std::string& scheduleName : m_db.listAllScheduleNames()) {
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800155 const Schedule& schedule = m_db.getSchedule(scheduleName);
156 std::tie(isPositive, tempInterval) = schedule.getCoveringInterval(timeslot);
157
158 if (isPositive) {
159 if (!positiveResult.isValid())
160 positiveResult = tempInterval;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700161 positiveResult&& tempInterval;
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800162
163 std::map<Name, Buffer> m = m_db.getScheduleMembers(scheduleName);
164 memberKeys.insert(m.begin(), m.end());
165 }
166 else {
167 if (!negativeResult.isValid())
168 negativeResult = tempInterval;
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700169 negativeResult&& tempInterval;
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800170 }
171 }
172 if (!positiveResult.isValid()) {
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700173 // return invalid interval when there is no member has interval covering the
174 // time slot
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800175 return Interval(false);
176 }
177
178 // get the final interval result
179 if (negativeResult.isValid())
180 finalInterval = positiveResult && negativeResult;
181 else
182 finalInterval = positiveResult;
183
184 return finalInterval;
185}
186
187void
188GroupManager::generateKeyPairs(Buffer& priKeyBuf, Buffer& pubKeyBuf) const
189{
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800190 RsaKeyParams params(m_paramLength);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700191 DecryptKey<algo::Rsa> privateKey = algo::Rsa::generateKey(params);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800192 priKeyBuf = privateKey.getKeyBits();
193 EncryptKey<algo::Rsa> publicKey = algo::Rsa::deriveEncryptKey(priKeyBuf);
194 pubKeyBuf = publicKey.getKeyBits();
195}
196
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800197Data
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700198GroupManager::createEKeyData(const std::string& startTs,
199 const std::string& endTs,
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800200 const Buffer& pubKeyBuf)
201{
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800202 Name name(m_namespace);
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800203 name.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800204 Data data(name);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800205 data.setFreshnessPeriod(time::hours(m_freshPeriod));
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700206 data.setContent(pubKeyBuf.data(), pubKeyBuf.size());
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800207 m_keyChain.sign(data);
208 return data;
209}
210
211Data
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700212GroupManager::createDKeyData(const std::string& startTs,
213 const std::string& endTs,
214 const Name& keyName,
215 const Buffer& priKeyBuf,
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800216 const Buffer& certKey)
217{
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800218 Name name(m_namespace);
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800219 name.append(NAME_COMPONENT_D_KEY);
220 name.append(startTs).append(endTs);
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800221 Data data = Data(name);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800222 data.setFreshnessPeriod(time::hours(m_freshPeriod));
Yingdi Yu883f4202015-11-02 13:54:11 -0800223 algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700224 algo::encryptData(data,
225 priKeyBuf.data(),
226 priKeyBuf.size(),
227 keyName,
228 certKey.data(),
229 certKey.size(),
230 eparams);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800231 m_keyChain.sign(data);
232 return data;
233}
234
Zhiyi Zhang67f90aa2016-10-16 14:29:15 -0700235void
236GroupManager::addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey)
237{
238 m_db.addEKey(eKeyName, pubKey, priKey);
239}
240
241std::tuple<Buffer, Buffer>
242GroupManager::getEKey(const Name& eKeyName)
243{
244 return m_db.getEKey(eKeyName);
245}
246
247void
248GroupManager::deleteEKey(const Name& eKeyName)
249{
250 m_db.deleteEKey(eKeyName);
251}
252
253void
254GroupManager::cleanEKeys()
255{
256 m_db.cleanEKeys();
257}
258
Alexander Afanasyev9091d832018-04-18 17:21:08 -0400259} // namespace nac
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800260} // namespace ndn