Go to the documentation of this file.00001 #include "ibrdtn/security/PayloadIntegrityBlock.h"
00002 #include "ibrdtn/security/MutualSerializer.h"
00003 #include "ibrdtn/data/Bundle.h"
00004
00005 #include <ibrcommon/ssl/RSASHA256Stream.h>
00006 #include <ibrcommon/Logger.h>
00007 #include <openssl/err.h>
00008 #include <openssl/rsa.h>
00009
00010 #ifdef __DEVELOPMENT_ASSERTIONS__
00011 #include <cassert>
00012 #endif
00013
00014 namespace dtn
00015 {
00016 namespace security
00017 {
00018 dtn::data::Block* PayloadIntegrityBlock::Factory::create()
00019 {
00020 return new PayloadIntegrityBlock();
00021 }
00022
00023 PayloadIntegrityBlock::PayloadIntegrityBlock()
00024 : SecurityBlock(PAYLOAD_INTEGRITY_BLOCK, PIB_RSA_SHA256), result_size(0)
00025 {
00026 }
00027
00028 PayloadIntegrityBlock::~PayloadIntegrityBlock()
00029 {
00030 }
00031
00032 size_t PayloadIntegrityBlock::getSecurityResultSize() const
00033 {
00034 if (result_size > 0)
00035 {
00036 return result_size;
00037 }
00038
00039 return SecurityBlock::getSecurityResultSize();
00040 }
00041
00042 void PayloadIntegrityBlock::sign(dtn::data::Bundle &bundle, const SecurityKey &key, const dtn::data::EID& destination)
00043 {
00044 PayloadIntegrityBlock& pib = bundle.push_front<PayloadIntegrityBlock>();
00045 pib.set(REPLICATE_IN_EVERY_FRAGMENT, true);
00046
00047
00048 if (bundle.get(dtn::data::PrimaryBlock::FRAGMENT))
00049 {
00050 dtn::data::PayloadBlock& plb = bundle.getBlock<dtn::data::PayloadBlock>();
00051 ibrcommon::BLOB::Reference blobref = plb.getBLOB();
00052 ibrcommon::BLOB::iostream stream = blobref.iostream();
00053 addFragmentRange(pib._ciphersuite_params, bundle._fragmentoffset, stream.size());
00054 }
00055
00056
00057 if (key.reference != bundle._source.getNodeEID()) pib.setSecuritySource( key.reference );
00058 if (destination != bundle._destination.getNodeEID()) pib.setSecurityDestination( destination );
00059
00060 pib.setResultSize(key);
00061 pib.setCiphersuiteId(SecurityBlock::PIB_RSA_SHA256);
00062 pib._ciphersuite_flags |= CONTAINS_SECURITY_RESULT;
00063 std::string sign = calcHash(bundle, key, pib);
00064 pib._security_result.set(SecurityBlock::integrity_signature, sign);
00065 }
00066
00067 const std::string PayloadIntegrityBlock::calcHash(const dtn::data::Bundle &bundle, const SecurityKey &key, PayloadIntegrityBlock& ignore)
00068 {
00069 EVP_PKEY *pkey = key.getEVP();
00070 ibrcommon::RSASHA256Stream rs2s(pkey);
00071
00072
00073 dtn::security::MutualSerializer ms(rs2s, &ignore);
00074 ms << bundle; rs2s << std::flush;
00075
00076 int return_code = rs2s.getSign().first;
00077 std::string sign_string = rs2s.getSign().second;
00078 SecurityKey::free(pkey);
00079
00080 if (return_code)
00081 return sign_string;
00082 else
00083 {
00084 IBRCOMMON_LOGGER_ex(critical) << "an error occured at the creation of the hash and it is invalid" << IBRCOMMON_LOGGER_ENDL;
00085 ERR_print_errors_fp(stderr);
00086 return std::string("");
00087 }
00088 }
00089
00090 void PayloadIntegrityBlock::verify(const dtn::data::Bundle& bundle, const SecurityKey &key, const PayloadIntegrityBlock &sb, const bool use_eid)
00091 {
00092
00093 if (use_eid)
00094 {
00095 if (!sb.isSecuritySource(bundle, key.reference))
00096 {
00097 throw ibrcommon::Exception("key not match the security source");
00098 }
00099 }
00100
00101
00102 if (sb._ciphersuite_id != SecurityBlock::PIB_RSA_SHA256)
00103 {
00104 throw ibrcommon::Exception("can not verify the PIB because of an invalid algorithm");
00105 }
00106
00107 EVP_PKEY *pkey = key.getEVP();
00108 if (pkey == NULL) throw ibrcommon::Exception("verification error");
00109
00110 ibrcommon::RSASHA256Stream rs2s(pkey, true);
00111
00112
00113 dtn::security::MutualSerializer ms(rs2s, &sb);
00114 ms << bundle; rs2s << std::flush;
00115
00116 int ret = rs2s.getVerification(sb._security_result.get(SecurityBlock::integrity_signature));
00117 SecurityKey::free(pkey);
00118
00119 if (ret == 0)
00120 {
00121 throw ibrcommon::Exception("verification failed");
00122 }
00123 else if (ret < 0)
00124 {
00125 throw ibrcommon::Exception("verification error");
00126 }
00127 }
00128
00129 void PayloadIntegrityBlock::verify(const dtn::data::Bundle &bundle, const SecurityKey &key)
00130 {
00131
00132 std::list<const PayloadIntegrityBlock *> pibs = bundle.getBlocks<PayloadIntegrityBlock>();
00133
00134 for (std::list<const PayloadIntegrityBlock *>::const_iterator it = pibs.begin(); it!=pibs.end(); it++)
00135 {
00136 verify(bundle, key, **it);
00137 }
00138 }
00139
00140 void PayloadIntegrityBlock::setResultSize(const SecurityKey &key)
00141 {
00142 EVP_PKEY *pkey = key.getEVP();
00143
00144
00145 if ((result_size = EVP_PKEY_size(pkey)) > 0)
00146 {
00147
00148 result_size += dtn::data::SDNV(result_size).getLength();
00149
00150
00151 result_size++;
00152 }
00153 else
00154 {
00155 result_size = _security_result.getLength();
00156 }
00157
00158 SecurityKey::free(pkey);
00159 }
00160
00161 void PayloadIntegrityBlock::strip(dtn::data::Bundle& bundle, const SecurityKey &key, const bool all)
00162 {
00163 std::list<const PayloadIntegrityBlock *> pibs = bundle.getBlocks<PayloadIntegrityBlock>();
00164 const PayloadIntegrityBlock * valid = NULL;
00165
00166
00167 for (std::list<const PayloadIntegrityBlock *>::const_iterator it = pibs.begin(); it != pibs.end() && !valid; it++)
00168 {
00169 const PayloadIntegrityBlock &pib = (**it);
00170
00171
00172 try {
00173 verify(bundle, key, pib);
00174
00175
00176 bundle.remove(pib);
00177
00178
00179 if (all && (it != pibs.begin()))
00180 {
00181
00182 for (it--; it != pibs.begin(); it--)
00183 {
00184 bundle.remove(**it);
00185 }
00186
00187
00188 bundle.remove(**it);
00189 }
00190
00191 return;
00192 } catch (const ibrcommon::Exception&) { };
00193 }
00194 }
00195
00196 void PayloadIntegrityBlock::strip(dtn::data::Bundle& bundle)
00197 {
00198 std::list<const PayloadIntegrityBlock *> pibs = bundle.getBlocks<PayloadIntegrityBlock>();
00199 for (std::list<const PayloadIntegrityBlock *>::const_iterator it = pibs.begin(); it != pibs.end(); it++)
00200 {
00201 bundle.remove(*(*it));
00202 }
00203 }
00204
00205 std::istream& PayloadIntegrityBlock::deserialize(std::istream &stream)
00206 {
00207
00208 SecurityBlock::deserialize(stream);
00209
00210
00211 result_size = _security_result.getLength();
00212
00213 return stream;
00214 }
00215 }
00216 }