IBR-DTN  1.0.0
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 
26 #include <ibrcommon/ssl/RSASHA256Stream.h>
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 
128  {
129  try {
130  // retrieve fragment range from ciphersuite params
131  dtn::data::Number offset;
132  dtn::data::Number length;
134 
135  // compare fragment range
136  if (offset != bundle.fragmentoffset) throw dtn::security::VerificationSkippedException();
137  if (length != bundle.getPayloadLength()) throw dtn::security::VerificationSkippedException();
138  } catch (const dtn::security::ElementMissingException&) {
139  // this PIB is not mentioned to verify a fragment
141  }
142  }
143 
144  // check the correct algorithm
146  {
147  throw VerificationFailedException("can not verify the PIB because of an invalid algorithm");
148  }
149 
150  EVP_PKEY *pkey = key.getEVP();
151  if (pkey == NULL) throw VerificationFailedException("verification error");
152 
153  ibrcommon::RSASHA256Stream rs2s(pkey, true);
154 
155  // serialize the bundle in the mutable form
156  dtn::security::MutableSerializer ms(rs2s, &sb);
157  (dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush;
158 
159  try {
160  int ret = rs2s.getVerification(sb._security_result.get(SecurityBlock::integrity_signature));
161  SecurityKey::free(pkey);
162 
163  if (ret > 0)
164  {
165  // success!
166  return;
167  }
168  else if (ret < 0)
169  {
170  throw VerificationFailedException("verification error");
171  }
172  } catch (const ElementMissingException&) {
173  // This PIB can not verified due to a missing integrity signature
174  throw VerificationFailedException("Integrity signature is missing!");
175  }
176  }
177 
178  throw VerificationFailedException("verification failed");
179  }
180 
181  void PayloadIntegrityBlock::setResultSize(const SecurityKey &key)
182  {
183  EVP_PKEY *pkey = key.getEVP();
184 
185  // size of integrity_signature
186  if ((result_size = EVP_PKEY_size(pkey)) > 0)
187  {
188  // sdnv length
189  result_size += dtn::data::Number(result_size).getLength();
190 
191  // type
192  result_size++;
193  }
194  else
195  {
196  result_size = _security_result.getLength();
197  }
198 
199  SecurityKey::free(pkey);
200  }
201 
203  {
204  bundle.erase(std::remove(bundle.begin(), bundle.end(), PayloadIntegrityBlock::BLOCK_TYPE), bundle.end());
205  }
206 
207  std::istream& PayloadIntegrityBlock::deserialize(std::istream &stream, const dtn::data::Length &length)
208  {
209  // deserialize the SecurityBlock
210  SecurityBlock::deserialize(stream, length);
211 
212  // set the key size locally
213  result_size = _security_result.getLength();
214 
215  return stream;
216  }
217  }
218 }
dtn::data::Bitset< CIPHERSUITE_FLAGS > _ciphersuite_flags
bool sameHost(const std::string &other) const
Definition: EID.cpp:322
T & push_front()
Definition: Bundle.h:161
size_t Length
Definition: Number.h:33
virtual EVP_PKEY * getEVP() const
Definition: SecurityKey.cpp:89
static void free(RSA *key)
Definition: SecurityKey.cpp:44
virtual std::istream & deserialize(std::istream &stream, const dtn::data::Length &length)
void set(ProcFlags flag, const bool &value)
Definition: Block.cpp:77
size_t getLength() const
Definition: SDNV.h:99
void set(TLV_TYPES type, std::string value)
void setSecurityDestination(const dtn::data::EID &destination)
virtual dtn::data::Length getSecurityResultSize() const
void erase(iterator it)
Definition: Bundle.cpp:127
dtn::data::Length getPayloadLength() const
Definition: Bundle.cpp:292
iterator begin()
Definition: Bundle.cpp:49
void setCiphersuiteId(const CIPHERSUITE_IDS id)
const std::string get(TLV_TYPES type) const
dtn::data::Length getLength() const
bool get(FLAGS flag) const
static const dtn::data::block_t BLOCK_TYPE
virtual dtn::data::Length getSecurityResultSize() const
static void addFragmentRange(TLVList &ciphersuite_params, const dtn::data::Number &fragmentoffset, const dtn::data::Number &payload_length)
static void getFragmentRange(const TLVList &ciphersuite_params, dtn::data::Number &offset, dtn::data::Number &range)
dtn::data::EID reference
Definition: SecurityKey.h:74
unsigned char block_t
Definition: Number.h:37
iterator find(block_t blocktype)
Definition: Bundle.cpp:307
ibrcommon::BLOB::Reference getBLOB() const
static void verify(const dtn::data::Bundle &bundle, const SecurityKey &key)
dtn::data::Number _ciphersuite_id
bool isSecuritySource(const dtn::data::Bundle &, const dtn::data::EID &) const
dtn::data::SDNV< Size > Number
Definition: Number.h:38
static void strip(dtn::data::Bundle &bundle)
iterator end()
Definition: Bundle.cpp:54
void setSecuritySource(const dtn::data::EID &source)
dtn::data::Number fragmentoffset
Definition: BundleID.h:57
static void sign(dtn::data::Bundle &bundle, const SecurityKey &key, const dtn::data::EID &destination)
dtn::data::EID source
Definition: BundleID.h:53
virtual std::istream & deserialize(std::istream &stream, const dtn::data::Length &length)
ibrcommon::find_iterator< const_iterator, block_t > const_find_iterator
Definition: Bundle.h:80