IBR-DTNSuite  0.12
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  addFragmentRange(pib._ciphersuite_params, bundle.fragmentoffset, blobref.size());
78  }
79 
80  // set the source and destination address of the new block
81  if (!key.reference.sameHost(bundle.source)) pib.setSecuritySource( key.reference );
82  if (!destination.sameHost(bundle.destination)) pib.setSecurityDestination( destination );
83 
84  pib.setResultSize(key);
87  std::string sign = calcHash(bundle, key, pib);
89  }
90 
91  const std::string PayloadIntegrityBlock::calcHash(const dtn::data::Bundle &bundle, const SecurityKey &key, PayloadIntegrityBlock& ignore)
92  {
93  EVP_PKEY *pkey = key.getEVP();
94  ibrcommon::RSASHA256Stream rs2s(pkey);
95 
96  // serialize the bundle in the mutable form
97  dtn::security::MutableSerializer ms(rs2s, &ignore);
98  (dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush;
99 
100  int return_code = rs2s.getSign().first;
101  std::string sign_string = rs2s.getSign().second;
102  SecurityKey::free(pkey);
103 
104  if (return_code)
105  return sign_string;
106  else
107  {
108  IBRCOMMON_LOGGER_ex(critical) << "an error occured at the creation of the hash and it is invalid" << IBRCOMMON_LOGGER_ENDL;
109  ERR_print_errors_fp(stderr);
110  return std::string("");
111  }
112  }
113 
115  {
116  // iterate over all PIBs to find the right one
118 
119  while (it.next(bundle.end()))
120  {
121  const PayloadIntegrityBlock &sb = dynamic_cast<const PayloadIntegrityBlock&>(**it);
122 
123  // check if we have the public key of the security source
124  // skip this block if the given key isn't the right one
125  if (!sb.isSecuritySource(bundle, key.reference)) continue;
126 
127  // check the correct algorithm
129  {
130  throw VerificationFailedException("can not verify the PIB because of an invalid algorithm");
131  }
132 
133  EVP_PKEY *pkey = key.getEVP();
134  if (pkey == NULL) throw VerificationFailedException("verification error");
135 
136  ibrcommon::RSASHA256Stream rs2s(pkey, true);
137 
138  // serialize the bundle in the mutable form
139  dtn::security::MutableSerializer ms(rs2s, &sb);
140  (dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush;
141 
142  try {
144  SecurityKey::free(pkey);
145 
146  if (ret > 0)
147  {
148  // success!
149  return;
150  }
151  else if (ret < 0)
152  {
153  throw VerificationFailedException("verification error");
154  }
155  } catch (const ElementMissingException&) {
156  // This PIB can not verified due to a missing integrity signature
157  throw VerificationFailedException("Integrity signature is missing!");
158  }
159  }
160 
161  throw VerificationFailedException("verification failed");
162  }
163 
164  void PayloadIntegrityBlock::setResultSize(const SecurityKey &key)
165  {
166  EVP_PKEY *pkey = key.getEVP();
167 
168  // size of integrity_signature
169  if ((result_size = EVP_PKEY_size(pkey)) > 0)
170  {
171  // sdnv length
172  result_size += dtn::data::Number(result_size).getLength();
173 
174  // type
175  result_size++;
176  }
177  else
178  {
179  result_size = _security_result.getLength();
180  }
181 
182  SecurityKey::free(pkey);
183  }
184 
186  {
187  bundle.erase(std::remove(bundle.begin(), bundle.end(), PayloadIntegrityBlock::BLOCK_TYPE), bundle.end());
188  }
189 
190  std::istream& PayloadIntegrityBlock::deserialize(std::istream &stream, const dtn::data::Length &length)
191  {
192  // deserialize the SecurityBlock
193  SecurityBlock::deserialize(stream, length);
194 
195  // set the key size locally
196  result_size = _security_result.getLength();
197 
198  return stream;
199  }
200  }
201 }