00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #ifdef BSP_ENABLED
00022
00023 #include "Ciphersuite_BA1.h"
00024 #include "bundling/Bundle.h"
00025 #include "bundling/BundleDaemon.h"
00026 #include "bundling/BundleProtocol.h"
00027 #include "bundling/SDNV.h"
00028 #include "contacts/Link.h"
00029 #include "KeyDB.h"
00030 #include "BP_Tag.h"
00031 #include "openssl/hmac.h"
00032
00033 namespace dtn {
00034
00035 static const char* log = "/dtn/bundle/ciphersuite";
00036
00037
00038 Ciphersuite_BA1::Ciphersuite_BA1()
00039 {
00040 }
00041
00042
00043 u_int16_t
00044 Ciphersuite_BA1::cs_num(void)
00045 {
00046 return CSNUM_BA1;
00047 }
00048
00049
00050 int
00051 Ciphersuite_BA1::consume(Bundle* bundle, BlockInfo* block,
00052 u_char* buf, size_t len)
00053 {
00054 log_debug_p(log, "Ciphersuite_BA1::consume()");
00055 int cc = block->owner()->consume(bundle, block, buf, len);
00056
00057 if (cc == -1) {
00058 return -1;
00059 }
00060
00061
00062
00063
00064 if (! block->complete()) {
00065 ASSERT(cc == (int)len);
00066 return cc;
00067 }
00068
00069 if ( block->locals() == NULL ) {
00070 parse(block);
00071 }
00072
00073 return cc;
00074 }
00075
00076
00077 bool
00078 Ciphersuite_BA1::validate(const Bundle* bundle,
00079 BlockInfoVec* block_list,
00080 BlockInfo* block,
00081 status_report_reason_t* reception_reason,
00082 status_report_reason_t* deletion_reason)
00083 {
00084 (void)block_list;
00085 size_t offset;
00086 size_t len;
00087 size_t rem;
00088 HMAC_CTX ctx;
00089 OpaqueContext* r = reinterpret_cast<OpaqueContext*>(&ctx);
00090 const BlockInfoVec& recv_blocks = bundle->recv_blocks();
00091 u_char result[EVP_MAX_MD_SIZE];
00092 u_int32_t rlen = 0;
00093 BP_Local_CS* locals = NULL;
00094 u_char* buf;
00095 u_int64_t cs_flags;
00096 u_int64_t suite_num;
00097 u_int64_t field_length = 0LL;
00098 int sdnv_len = 0;
00099 (void)reception_reason;
00100
00101 log_debug_p(log, "Ciphersuite_BA1::validate()");
00102
00103 locals = dynamic_cast<BP_Local_CS*>(block->locals());
00104 CS_FAIL_IF_NULL(locals);
00105 if ( !(locals->cs_flags() & Ciphersuite::CS_BLOCK_HAS_RESULT) ) {
00106 const KeyDB::Entry* key_entry =
00107 KeyDB::find_key(EndpointID(locals->security_src()).uri().host().c_str(), cs_num());
00108 if (key_entry == NULL) {
00109 log_warn_p(log, "unable to find verification key for this block");
00110 goto fail;
00111 }
00112 ASSERT(key_entry->key_len() == res_len);
00113
00114
00115
00116
00117
00118
00119
00120
00121 HMAC_CTX_init(&ctx);
00122 HMAC_Init_ex(&ctx, key_entry->key(), key_entry->key_len(),
00123 EVP_sha1(), NULL);
00124
00125
00126 for ( BlockInfoVec::const_iterator iter = recv_blocks.begin();
00127 iter != recv_blocks.end();
00128 ++iter)
00129 {
00130 offset = 0;
00131 len = iter->full_length();
00132
00133 if ( iter->type() == BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK ) {
00134
00135
00136
00137
00138
00139 u_char* ptr = iter->data();
00140 rem = iter->full_length();
00141
00142 sdnv_len = SDNV::decode(ptr,
00143 rem,
00144 &suite_num);
00145 ptr += sdnv_len;
00146 rem -= sdnv_len;
00147
00148 sdnv_len = SDNV::decode(ptr,
00149 rem,
00150 &cs_flags);
00151 ptr += sdnv_len;
00152 rem -= sdnv_len;
00153
00154 if ( cs_flags & CS_BLOCK_HAS_RESULT ) {
00155
00156
00157 sdnv_len = SDNV::len(ptr);
00158 ptr += sdnv_len;
00159 rem -= sdnv_len;
00160
00161 sdnv_len = SDNV::len(ptr);
00162 ptr += sdnv_len;
00163 rem -= sdnv_len;
00164
00165 len = ptr - iter->contents().buf();
00166 }
00167 }
00168
00169 iter->owner()->process( Ciphersuite_BA1::digest,
00170 bundle,
00171 block,
00172 &*iter,
00173 offset,
00174 len,
00175 r);
00176 }
00177
00178
00179 HMAC_Final(&ctx, result, &rlen);
00180 HMAC_cleanup(&ctx);
00181 ASSERT(rlen == Ciphersuite_BA1::res_len);
00182
00183
00184
00185 for (BlockInfoVec::iterator iter = block_list->begin();
00186 iter != block_list->end();
00187 ++iter)
00188 {
00189 BP_Local_CS* target_locals;
00190 if ( iter->type() != BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK )
00191 continue;
00192
00193 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
00194 CS_FAIL_IF_NULL(target_locals);
00195 if ( target_locals->owner_cs_num() != CSNUM_BA1 )
00196 continue;
00197
00198 if (target_locals->correlator() != locals->correlator() )
00199 continue;
00200
00201
00202
00203
00204
00205
00206 if ( target_locals->cs_flags() & Ciphersuite::CS_BLOCK_HAS_RESULT ) {
00207 buf = target_locals->security_result().buf();
00208 len = target_locals->security_result().len();
00209
00210
00211 if ( *buf++ != Ciphersuite::CS_signature_field ) {
00212 log_err_p(log, "Ciphersuite_BA1 item type incorrect");
00213 goto fail;
00214 }
00215 len--;
00216
00217 sdnv_len = SDNV::decode(buf, len, &field_length);
00218 buf += sdnv_len;
00219 len -= sdnv_len;
00220 ASSERT(field_length == Ciphersuite_BA1::res_len);
00221 ASSERT( len == Ciphersuite_BA1::res_len);
00222
00223 if ( memcmp(buf, result, Ciphersuite_BA1::res_len) != 0) {
00224 log_err_p(log, "block failed security validation Ciphersuite_BA1");
00225 goto fail;
00226 } else {
00227 log_debug_p(log, "block passed security validation Ciphersuite_BA1");
00228 locals->set_proc_flag(CS_BLOCK_PASSED_VALIDATION);
00229 return true;
00230 }
00231 }
00232 else
00233 {
00234 continue;
00235 }
00236 }
00237 log_err_p(log, "block failed security validation Ciphersuite_BA1 - result is missing");
00238 goto fail;
00239 }
00240 else
00241 {
00242
00243 log_debug_p(log, "BA1BlockProcessor::validate(): no check on this block");
00244 }
00245
00246 return true;
00247
00248 fail:
00249 locals->set_proc_flag(CS_BLOCK_FAILED_VALIDATION | CS_BLOCK_COMPLETED_DO_NOT_FORWARD);
00250 *deletion_reason = BundleProtocol::REASON_SECURITY_FAILED;
00251 return false;
00252 }
00253
00254
00255 int
00256 Ciphersuite_BA1::prepare(const Bundle* bundle,
00257 BlockInfoVec* xmit_blocks,
00258 const BlockInfo* source,
00259 const LinkRef& link,
00260 list_owner_t list)
00261 {
00262 (void)bundle;
00263 (void)link;
00264
00265 int result = BP_FAIL;
00266 u_int64_t correlator = CSNUM_BA1 << 16;
00267 u_int16_t flags = CS_BLOCK_HAS_CORRELATOR;
00268 BP_Local_CS* locals = NULL;
00269
00270 log_debug_p(log, "Ciphersuite_BA1::prepare()");
00271 if ( list == BlockInfo::LIST_RECEIVED )
00272 return BP_SUCCESS;
00273
00274
00275
00276 BlockInfo bi = BlockInfo(BundleProtocol::find_processor(BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK), source);
00277
00278
00279 BundleDaemon* bd = BundleDaemon::instance();
00280 bi.set_locals(new BP_Local_CS);
00281 locals = dynamic_cast<BP_Local_CS*>(bi.locals());
00282 CS_FAIL_IF_NULL(locals);
00283 locals->set_owner_cs_num(CSNUM_BA1);
00284 locals->set_cs_flags(flags | CS_BLOCK_HAS_SOURCE);
00285 locals->set_security_src(bd->local_eid().str());
00286 correlator = create_correlator(bundle, xmit_blocks);
00287 correlator |= (int)CSNUM_BA1 << 16;
00288 locals->set_correlator( correlator );
00289 locals->set_correlator_sequence( 0 );
00290
00291
00292
00293
00294
00295
00296
00297 if ( xmit_blocks->size() > 0 ) {
00298 BlockInfoVec::iterator iter = xmit_blocks->begin();
00299 if ( iter->type() == BundleProtocol::PRIMARY_BLOCK)
00300 ++iter;
00301 xmit_blocks->insert(iter, bi);
00302 } else {
00303 xmit_blocks->push_back(bi);
00304 }
00305
00306
00307 bi.set_locals(new BP_Local_CS);
00308 locals = dynamic_cast<BP_Local_CS*>(bi.locals());
00309 CS_FAIL_IF_NULL(locals);
00310 locals->set_owner_cs_num(CSNUM_BA1);
00311 locals->set_cs_flags(flags | CS_BLOCK_HAS_RESULT);
00312 locals->set_correlator( correlator );
00313 locals->set_correlator_sequence( 1 );
00314 xmit_blocks->push_back(bi);
00315
00316 result = BP_SUCCESS;
00317 return result;
00318
00319 fail:
00320 if ( locals != NULL )
00321 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
00322 return BP_FAIL;
00323 }
00324
00325
00326 int
00327 Ciphersuite_BA1::generate(const Bundle* bundle,
00328 BlockInfoVec* xmit_blocks,
00329 BlockInfo* block,
00330 const LinkRef& link,
00331 bool last)
00332 {
00333 (void)bundle;
00334 (void)link;
00335 (void)xmit_blocks;
00336
00337 log_debug_p(log, "Ciphersuite_BA1::generate()");
00338 int result = BP_FAIL;
00339 BP_Local_CS* locals = dynamic_cast<BP_Local_CS*>(block->locals());
00340 u_int16_t flags = locals->cs_flags();
00341 size_t item_len = 0;
00342 u_char* buf = NULL;
00343 int len = 0;
00344 size_t length = 0;
00345 int sdnv_len = 0;
00346 BlockInfo::DataBuffer* contents = NULL;
00347
00348 CS_FAIL_IF_NULL(locals);
00349
00350 if ( flags & CS_BLOCK_HAS_SOURCE ) {
00351 block->add_eid(locals->security_src());
00352
00353
00354 }
00355
00356 length = 0;
00357 length += SDNV::encoding_len(CSNUM_BA1);
00358 length += SDNV::encoding_len(locals->cs_flags());
00359 length += SDNV::encoding_len(locals->correlator());
00360
00361 if (flags & CS_BLOCK_HAS_RESULT) {
00362 item_len = 1 + 1 + Ciphersuite_BA1::res_len;
00363 length += SDNV::encoding_len(item_len) + item_len;
00364 }
00365
00366 generate_preamble(xmit_blocks,
00367 block,
00368 BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK,
00369 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
00370 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
00371 length);
00372
00373 contents = block->writable_contents();
00374 contents->reserve(block->data_offset() + length);
00375 contents->set_len(block->data_offset() + length);
00376
00377 buf = contents->buf() + block->data_offset();
00378 len = length;
00379
00380
00381 sdnv_len = SDNV::encode(CSNUM_BA1, buf, len);
00382 CS_FAIL_IF(sdnv_len <= 0);
00383 buf += sdnv_len;
00384 len -= sdnv_len;
00385
00386 sdnv_len = SDNV::encode(locals->cs_flags(), buf, len);
00387 CS_FAIL_IF(sdnv_len <= 0);
00388 buf += sdnv_len;
00389 len -= sdnv_len;
00390
00391
00392 sdnv_len = SDNV::encode(locals->correlator(), buf, len);
00393 CS_FAIL_IF(sdnv_len <= 0);
00394 buf += sdnv_len;
00395 len -= sdnv_len;
00396
00397 if (flags & CS_BLOCK_HAS_RESULT) {
00398
00399 size_t result_offset = buf - block->data();
00400 locals->set_security_result_offset(result_offset);
00401
00402
00403 sdnv_len = SDNV::encode(item_len, buf, len);
00404 CS_FAIL_IF(sdnv_len <= 0);
00405 buf += sdnv_len;
00406 len -= sdnv_len;
00407 }
00408 CS_FAIL_IF(len != (int)item_len);
00409
00410 result = BP_SUCCESS;
00411 return result;
00412
00413 fail:
00414 if ( locals != NULL )
00415 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
00416 return BP_FAIL;
00417 }
00418
00419
00420 int
00421 Ciphersuite_BA1::finalize(const Bundle* bundle,
00422 BlockInfoVec* xmit_blocks,
00423 BlockInfo* block,
00424 const LinkRef& link)
00425 {
00426 (void)link;
00427
00428 size_t offset;
00429 size_t len;
00430 size_t rem;
00431 HMAC_CTX ctx;
00432 OpaqueContext* r = reinterpret_cast<OpaqueContext*>(&ctx);
00433 u_char digest_result[EVP_MAX_MD_SIZE];
00434 u_int32_t rlen = 0;
00435 int result = BP_FAIL;
00436 BP_Local_CS* locals = NULL;
00437 u_int64_t cs_flags;
00438 u_int64_t suite_num;
00439 int sdnv_len = 0;
00440 log_debug_p(log, "Ciphersuite_BA1::finalize()");
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 locals = dynamic_cast<BP_Local_CS*>(block->locals());
00452 CS_FAIL_IF_NULL(locals);
00453 if ( locals->correlator_sequence() == 0 ) {
00454
00455 const KeyDB::Entry* key_entry = KeyDB::find_key("*", cs_num());
00456
00457
00458
00459 CS_FAIL_IF(key_entry == NULL);
00460 CS_FAIL_IF(key_entry->key_len() != res_len);
00461
00462
00463
00464
00465
00466
00467
00468
00469 HMAC_CTX_init(&ctx);
00470 HMAC_Init_ex(&ctx, key_entry->key(), key_entry->key_len(),
00471 EVP_sha1(), NULL);
00472
00473
00474 for (BlockInfoVec::const_iterator iter = xmit_blocks->begin();
00475 iter != xmit_blocks->end();
00476 ++iter)
00477 {
00478 offset = 0;
00479 len = iter->full_length();
00480
00481
00482
00483
00484 if ( iter->type() == BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK ) {
00485
00486
00487
00488
00489
00490 u_char* ptr = iter->data();
00491 rem = iter->full_length();
00492 sdnv_len = SDNV::decode(ptr,
00493 rem,
00494 &suite_num);
00495 ptr += sdnv_len;
00496 rem -= sdnv_len;
00497
00498 sdnv_len = SDNV::decode(ptr,
00499 rem,
00500 &cs_flags);
00501 ptr += sdnv_len;
00502 rem -= sdnv_len;
00503
00504 if ( cs_flags & CS_BLOCK_HAS_RESULT ) {
00505
00506
00507 sdnv_len = SDNV::len(ptr);
00508 ptr += sdnv_len;
00509 rem -= sdnv_len;
00510
00511 sdnv_len = SDNV::len(ptr);
00512 ptr += sdnv_len;
00513 rem -= sdnv_len;
00514
00515 len = ptr - iter->contents().buf();
00516 }
00517 }
00518
00519 iter->owner()->process( Ciphersuite_BA1::digest,
00520 bundle,
00521 block,
00522 &*iter,
00523 offset,
00524 len,
00525 r );
00526 }
00527
00528
00529 HMAC_Final(&ctx, digest_result, &rlen);
00530 HMAC_cleanup(&ctx);
00531 CS_FAIL_IF(rlen != Ciphersuite_BA1::res_len);
00532
00533
00534
00535 for (BlockInfoVec::iterator iter = xmit_blocks->begin();
00536 iter != xmit_blocks->end();
00537 ++iter)
00538 {
00539 BP_Local_CS* target_locals;
00540 if ( iter->type() != BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK )
00541 continue;
00542
00543 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
00544 CS_FAIL_IF_NULL(target_locals);
00545 if ( target_locals->owner_cs_num() != CSNUM_BA1 )
00546 continue;
00547
00548 if (target_locals->correlator() != locals->correlator() )
00549 continue;
00550
00551 if (target_locals->correlator_sequence() != 1 )
00552 continue;
00553
00554
00555
00556
00557
00558
00559
00560 u_char* buf = iter->writable_contents()->buf() + iter->data_offset() + target_locals->security_result_offset();
00561 size_t rem = iter->data_length() - target_locals->security_result_offset();
00562 sdnv_len = SDNV::len(buf);
00563 CS_FAIL_IF(sdnv_len != 1);
00564 buf += sdnv_len;
00565 rem -= sdnv_len;
00566 *buf++ = Ciphersuite::CS_signature_field;
00567 rem--;
00568 sdnv_len = SDNV::encode(Ciphersuite_BA1::res_len, buf, rem);
00569 CS_FAIL_IF(sdnv_len != 1);
00570 buf += sdnv_len;
00571 rem -= sdnv_len;
00572 CS_FAIL_IF (rem != Ciphersuite_BA1::res_len);
00573 memcpy(buf, digest_result, Ciphersuite_BA1::res_len);
00574 }
00575 }
00576
00577 result = BP_SUCCESS;
00578 return result;
00579
00580 fail:
00581 if ( locals != NULL )
00582 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
00583 return BP_FAIL;
00584 }
00585
00586
00587 void
00588 Ciphersuite_BA1::digest(const Bundle* bundle,
00589 const BlockInfo* caller_block,
00590 const BlockInfo* target_block,
00591 const void* buf,
00592 size_t len,
00593 OpaqueContext* r)
00594 {
00595 (void)bundle;
00596 (void)caller_block;
00597 (void)target_block;
00598 log_debug_p(log, "Ciphersuite_BA1::digest() %zu bytes", len);
00599
00600 HMAC_CTX* pctx = reinterpret_cast<HMAC_CTX*>(r);
00601
00602 HMAC_Update( pctx, reinterpret_cast<const u_char*>(buf), len );
00603 }
00604
00605 }
00606
00607 #endif