IBR-DTN  1.0.0
SecurityKeyManager.cpp
Go to the documentation of this file.
1 /*
2  * SecurityKeyManager.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "Configuration.h"
23 #include "core/BundleCore.h"
25 #include <ibrdtn/data/DTNTime.h>
26 #include <ibrcommon/Logger.h>
27 #include <sstream>
28 #include <iomanip>
29 #include <fstream>
30 #include <fcntl.h>
31 
32 #include <openssl/pem.h>
33 #include <openssl/rsa.h>
34 #include <openssl/err.h>
35 
36 namespace dtn
37 {
38  namespace security
39  {
40  const std::string SecurityKeyManager::TAG = "SecurityKeyManager";
41 
43  {
44  static SecurityKeyManager instance;
45  return instance;
46  }
47 
48  SecurityKeyManager::SecurityKeyManager()
49  {
50  }
51 
53  {
54  }
55 
57  {
58  const dtn::daemon::Configuration::Security &sec = conf.getSecurity();
59 
60  if (sec.enabled())
61  {
62  IBRCOMMON_LOGGER_TAG(SecurityKeyManager::TAG, info) << "initialized; path: " << sec.getPath().getPath() << IBRCOMMON_LOGGER_ENDL;
63 
64  // store all paths locally
65  _path = sec.getPath();
66  _key = sec.getKey();
67  _ca = sec.getCertificate();
68 
69  // check if there is a local key
71  {
72  IBRCOMMON_LOGGER_TAG(SecurityKeyManager::TAG, info) << "generate a new local key-pair for " << dtn::core::BundleCore::local.getString() << IBRCOMMON_LOGGER_ENDL;
73 
74  // generate a new local key
76  }
77  }
78  else
79  {
80  _path = ibrcommon::File();
81  _key = ibrcommon::File();
82  _ca = ibrcommon::File();
83  }
84  }
85 
86  const std::string SecurityKeyManager::hash(const dtn::data::EID &eid)
87  {
88  return hash(eid.getNode().getString());
89  }
90 
91  const std::string SecurityKeyManager::hash(const std::string &value)
92  {
93  std::stringstream ss;
94  for (std::string::const_iterator iter = value.begin(); iter != value.end(); ++iter)
95  {
96  unsigned char c = (*iter);
97  ss << std::hex << std::setw( 2 ) << std::setfill( '0' ) << (unsigned int)c;
98  }
99  return ss.str();
100  }
101 
103  {
104  ibrcommon::File keyfile = getKeyFile(ref, type);
105  return keyfile.exists();
106  }
107 
108  void SecurityKeyManager::createRSA(const dtn::data::EID &ref, const int bits)
109  {
110  const ibrcommon::File privkey = getKeyFile(ref, SecurityKey::KEY_PRIVATE);
111  const ibrcommon::File pubkey = getKeyFile(ref, SecurityKey::KEY_PUBLIC);
112  RSA* rsa = RSA_new();
113  BIGNUM* e = BN_new();
114 
115  BN_set_word(e, 65537);
116 
117  RSA_generate_key_ex(rsa, bits, e, NULL);
118 
119  BN_free(e);
120  e = NULL;
121 
122  // write private key
123  int fd = ::open(privkey.getPath().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0600);
124 
125  FILE * rsa_privkey_file = fdopen(fd, "w");
126  if (!rsa_privkey_file) {
127  IBRCOMMON_LOGGER_TAG(SecurityKeyManager::TAG, error) << "Failed to open " << privkey.getPath() << IBRCOMMON_LOGGER_ENDL;
128  RSA_free(rsa);
129  return;
130  }
131  PEM_write_RSAPrivateKey(rsa_privkey_file, rsa, NULL, NULL, 0, NULL, NULL);
132  fclose(rsa_privkey_file);
133 
134  // write public key
135  FILE * rsa_pubkey_file = fopen(pubkey.getPath().c_str(), "w+");
136  if (!rsa_pubkey_file) {
137  IBRCOMMON_LOGGER_TAG(SecurityKeyManager::TAG, error) << "Failed to open " << privkey.getPath() << IBRCOMMON_LOGGER_ENDL;
138  RSA_free(rsa);
139  return;
140  }
141  PEM_write_RSA_PUBKEY(rsa_pubkey_file, rsa);
142  fclose(rsa_pubkey_file);
143 
144  RSA_free(rsa);
145 
146  // set trust-level to high
147  SecurityKey key = get(ref, SecurityKey::KEY_PUBLIC);
148  key.trustlevel = SecurityKey::HIGH;
149  store(key);
150  }
151 
153  {
155  keydata.reference = ref.getNode();
156  keydata.type = type;
157  keydata.file = getKeyFile(prefix, keydata.reference, type);
158 
159  // load security key
160  load(keydata);
161 
162  return keydata;
163  }
164 
166  {
168  keydata.reference = ref.getNode();
169  keydata.type = type;
170  keydata.file = getKeyFile(keydata.reference, type);
171 
172  if ((keydata.type == SecurityKey::KEY_SHARED) && !keydata.file.exists())
173  {
174  // get the default shared key
175  ibrcommon::File default_key = dtn::daemon::Configuration::getInstance().getSecurity().getBABDefaultKey();
176 
177  if (default_key.exists()) {
178  keydata.file = default_key;
179  }
180  }
181 
182  // load security key
183  load(keydata);
184 
185  return keydata;
186  }
187 
188  void SecurityKeyManager::load(dtn::security::SecurityKey &keydata) const
189  {
190  // throw exception if key-file does not exists
191  if (!keydata.file.exists())
192  {
193  std::stringstream ss;
194  ss << "Key file for " << keydata.reference.getString() << " (" << keydata.file.getPath() << ") not found";
195  throw SecurityKey::KeyNotFoundException(ss.str());
196  }
197 
198  // load meta-data
199  if (keydata.getMetaFilename().exists())
200  {
201  std::ifstream metastream(keydata.getMetaFilename().getPath().c_str(), std::ios::in);
202  metastream >> keydata;
203  }
204  }
205 
207  {
208  std::stringstream ss;
209  {
210  ifstream stream(key.file.getPath().c_str(), std::iostream::in);
211  ss << stream.rdbuf();
212  }
213  store(key, ss.str());
214  }
215 
216  void SecurityKeyManager::store(const dtn::security::SecurityKey &key, const std::string &data)
217  {
218  dtn::security::SecurityKey keydata = key;
219 
220  // get the path for the key
221  keydata.file = getKeyFile(keydata.reference, keydata.type);
222 
223  std::ofstream keystream(keydata.file.getPath().c_str(), std::ios::out | std::ios::trunc);
224  keystream << data;
225  keystream.close();
226 
227  // store meta-data
228  std::ofstream metastream(keydata.getMetaFilename().getPath().c_str(), std::ios::out | std::ios::trunc);
229  metastream << key;
230  }
231 
232  void SecurityKeyManager::store(const std::string &prefix, const dtn::security::SecurityKey &key, const std::string &data)
233  {
234  dtn::security::SecurityKey keydata = key;
235 
236  // get the path for the key
237  keydata.file = getKeyFile(prefix, keydata.reference, keydata.type);
238 
239  std::ofstream keystream(keydata.file.getPath().c_str(), std::ios::out | std::ios::trunc);
240  keystream << data;
241  keystream.close();
242 
243  // store meta-data
244  std::ofstream metastream(keydata.getMetaFilename().getPath().c_str(), std::ios::out | std::ios::trunc);
245  metastream << key;
246  }
247 
249  {
250  // remove key file
251  ibrcommon::File keyfile = key.file;
252  keyfile.remove();
253 
254  // remove meta file
255  key.getMetaFilename().remove();
256  }
257 
258  const ibrcommon::File SecurityKeyManager::getKeyFile(const dtn::data::EID &peer, const dtn::security::SecurityKey::KeyType type) const
259  {
260  switch (type)
261  {
263  return _path.get(hash(peer) + ".mac");
264 
266  return _path.get(hash(peer) + ".pub");
267 
269  return _path.get(hash(peer) + ".pkey");
270 
271  default:
272  return _path.get(hash(peer) + ".key");
273  }
274  }
275 
276  const ibrcommon::File SecurityKeyManager::getKeyFile(const std::string &prefix, const dtn::data::EID &peer, const dtn::security::SecurityKey::KeyType type) const
277  {
278  switch (type)
279  {
281  return _path.get(hash(prefix) + "." + hash(peer) + ".mac");
282 
284  return _path.get(hash(prefix) + "." + hash(peer) + ".pub");
285 
287  return _path.get(hash(prefix) + "." + hash(peer) + ".pkey");
288 
289  default:
290  return _path.get(hash(prefix) + "." + hash(peer) + ".key");
291  }
292  }
293 
294  const ibrcommon::File SecurityKeyManager::getFilePath(const std::string &keyword, const std::string &extension) const
295  {
296  return _path.get(keyword + "." + extension);
297  }
298  }
299 }
static Configuration & getInstance(bool reset=false)
static SecurityKeyManager & getInstance()
const ibrcommon::File & getBABDefaultKey() const
static dtn::data::EID local
Definition: BundleCore.h:79
const Configuration::Security & getSecurity() const
ibrcommon::File file
Definition: SecurityKey.h:83
rsa_st RSA
Definition: SecurityBlock.h:35
const ibrcommon::File getKeyFile(const std::string &prefix, const dtn::data::EID &peer, const dtn::security::SecurityKey::KeyType type=dtn::security::SecurityKey::KEY_UNSPEC) const
const ibrcommon::File & getKey() const
const ibrcommon::File getFilePath(const std::string &keyword, const std::string &extension) const
const ibrcommon::File & getCertificate() const
EID getNode() const
Definition: EID.cpp:528
void remove(const SecurityKey &key)
dtn::security::SecurityKey get(const dtn::data::EID &ref, const dtn::security::SecurityKey::KeyType type=dtn::security::SecurityKey::KEY_UNSPEC) const
dtn::data::EID reference
Definition: SecurityKey.h:74
std::string getString() const
Definition: EID.cpp:374
bool hasKey(const dtn::data::EID &ref, const dtn::security::SecurityKey::KeyType type=dtn::security::SecurityKey::KEY_UNSPEC) const
void store(const dtn::security::SecurityKey &key, const std::string &data)
ibrcommon::File getMetaFilename() const
Definition: SecurityKey.cpp:59
const ibrcommon::File & getPath() const
virtual void onConfigurationChanged(const dtn::daemon::Configuration &conf)