IBR-DTNSuite  0.10
PayloadIntegrityBlock.cpp
Go to the documentation of this file.
1 /*
2  * PayloadIntegrityBlock.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 
24 #include "ibrdtn/data/Bundle.h"
25 
27 #include <ibrcommon/Logger.h>
28 #include <openssl/err.h>
29 #include <openssl/rsa.h>
30 
31 #include <algorithm>
32 
33 #ifdef __DEVELOPMENT_ASSERTIONS__
34 #include <cassert>
35 #endif
36 
37 namespace dtn
38 {
39  namespace security
40  {
42 
44  {
45  return new PayloadIntegrityBlock();
46  }
47 
50  {
51  }
52 
54  {
55  }
56 
58  {
59  if (result_size > 0)
60  {
61  return result_size;
62  }
63 
65  }
66 
67  void PayloadIntegrityBlock::sign(dtn::data::Bundle &bundle, const SecurityKey &key, const dtn::data::EID& destination)
68  {
71 
72  // check if this is a fragment
74  {
76  ibrcommon::BLOB::Reference blobref = plb.getBLOB();
77  ibrcommon::BLOB::iostream stream = blobref.iostream();
79  }
80 
81  // set the source and destination address of the new block
82  if (key.reference != bundle.source.getNode()) pib.setSecuritySource( key.reference );
83  if (destination != bundle.destination.getNode()) pib.setSecurityDestination( destination );
84 
85  pib.setResultSize(key);
88  std::string sign = calcHash(bundle, key, pib);
90  }
91 
92  const std::string PayloadIntegrityBlock::calcHash(const dtn::data::Bundle &bundle, const SecurityKey &key, PayloadIntegrityBlock& ignore)
93  {
94  EVP_PKEY *pkey = key.getEVP();
95  ibrcommon::RSASHA256Stream rs2s(pkey);
96 
97  // serialize the bundle in the mutable form
98  dtn::security::MutualSerializer ms(rs2s, &ignore);
99  (dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush;
100 
101  int return_code = rs2s.getSign().first;
102  std::string sign_string = rs2s.getSign().second;
103  SecurityKey::free(pkey);
104 
105  if (return_code)
106  return sign_string;
107  else
108  {
109  IBRCOMMON_LOGGER_ex(critical) << "an error occured at the creation of the hash and it is invalid" << IBRCOMMON_LOGGER_ENDL;
110  ERR_print_errors_fp(stderr);
111  return std::string("");
112  }
113  }
114 
115  void PayloadIntegrityBlock::verify(const dtn::data::Bundle& bundle, const SecurityKey &key, const PayloadIntegrityBlock &sb, const bool use_eid)
116  {
117  // check if we have the public key of the security source
118  if (use_eid)
119  {
120  if (!sb.isSecuritySource(bundle, key.reference))
121  {
122  throw ibrcommon::Exception("key not match the security source");
123  }
124  }
125 
126  // check the correct algorithm
127  if (sb._ciphersuite_id != SecurityBlock::PIB_RSA_SHA256)
128  {
129  throw ibrcommon::Exception("can not verify the PIB because of an invalid algorithm");
130  }
131 
132  EVP_PKEY *pkey = key.getEVP();
133  if (pkey == NULL) throw ibrcommon::Exception("verification error");
134 
135  ibrcommon::RSASHA256Stream rs2s(pkey, true);
136 
137  // serialize the bundle in the mutable form
138  dtn::security::MutualSerializer ms(rs2s, &sb);
139  (dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush;
140 
141  int ret = rs2s.getVerification(sb._security_result.get(SecurityBlock::integrity_signature));
142  SecurityKey::free(pkey);
143 
144  if (ret == 0)
145  {
146  throw ibrcommon::Exception("verification failed");
147  }
148  else if (ret < 0)
149  {
150  throw ibrcommon::Exception("verification error");
151  }
152  }
153 
155  {
156  // iterate over all PIBs to find the right one
158 
159  while (it.next(bundle.end()))
160  {
161  verify(bundle, key, dynamic_cast<const PayloadIntegrityBlock&>(**it));
162  }
163  }
164 
165  void PayloadIntegrityBlock::setResultSize(const SecurityKey &key)
166  {
167  EVP_PKEY *pkey = key.getEVP();
168 
169  // size of integrity_signature
170  if ((result_size = EVP_PKEY_size(pkey)) > 0)
171  {
172  // sdnv length
173  result_size += dtn::data::Number(result_size).getLength();
174 
175  // type
176  result_size++;
177  }
178  else
179  {
180  result_size = _security_result.getLength();
181  }
182 
183  SecurityKey::free(pkey);
184  }
185 
186  void PayloadIntegrityBlock::strip(dtn::data::Bundle& bundle, const SecurityKey &key, const bool all)
187  {
189 
190  // search for valid PIB
191  while (it.next(bundle.end()))
192  {
193  const PayloadIntegrityBlock &pib = dynamic_cast<const PayloadIntegrityBlock&>(**it);
194 
195  // check if the PIB is valid
196  try {
197  verify(bundle, key, pib);
198 
199  // found an valid PIB, remove it
200  bundle.remove(pib);
201 
202  // remove all previous pibs if all = true
203  if (all)
204  {
205  bundle.erase(std::remove(bundle.begin(), (dtn::data::Bundle::iterator&)it, PayloadIntegrityBlock::BLOCK_TYPE), bundle.end());
206  }
207 
208  return;
209  } catch (const ibrcommon::Exception&) { };
210  }
211  }
212 
214  {
215  bundle.erase(std::remove(bundle.begin(), bundle.end(), PayloadIntegrityBlock::BLOCK_TYPE), bundle.end());
216  }
217 
218  std::istream& PayloadIntegrityBlock::deserialize(std::istream &stream, const dtn::data::Length &length)
219  {
220  // deserialize the SecurityBlock
221  SecurityBlock::deserialize(stream, length);
222 
223  // set the key size locally
224  result_size = _security_result.getLength();
225 
226  return stream;
227  }
228  }
229 }