servlib/security/Ciphersuite_PI2.cc
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 2006 SPARTA Inc
       
     3  * 
       
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
       
     5  *    you may not use this file except in compliance with the License.
       
     6  *    You may obtain a copy of the License at
       
     7  * 
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  * 
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 #ifdef HAVE_CONFIG_H
       
    18 #  include <dtn-config.h>
       
    19 #endif
       
    20 
       
    21 #ifdef BSP_ENABLED
       
    22 
       
    23 #define OPENSSL_FIPS    1       /* required for sha256 */
       
    24 
       
    25 #include "Ciphersuite_PI2.h"
       
    26 #include "Ciphersuite_PC3.h"
       
    27 #include "bundling/Bundle.h"
       
    28 #include "bundling/BundleDaemon.h"
       
    29 #include "bundling/BundleProtocol.h"
       
    30 #include "bundling/SDNV.h"
       
    31 #include "contacts/Link.h"
       
    32 #include "security/KeySteward.h"
       
    33 #include "openssl/evp.h"
       
    34 
       
    35 namespace dtn {
       
    36 
       
    37 static const char * log = "/dtn/bundle/ciphersuite";
       
    38 
       
    39 /**
       
    40  * Local definition borrowed from PrimaryBlockProcessor.h
       
    41  * and with frag_offest and orig_length added
       
    42  */
       
    43 struct PrimaryBlock_ex {
       
    44     u_int8_t version;
       
    45     u_int64_t processing_flags;
       
    46     u_int64_t block_length;
       
    47     u_int64_t dest_scheme_offset;
       
    48     u_int64_t dest_ssp_offset;
       
    49     u_int64_t source_scheme_offset;
       
    50     u_int64_t source_ssp_offset;
       
    51     u_int64_t replyto_scheme_offset;
       
    52     u_int64_t replyto_ssp_offset;
       
    53     u_int64_t custodian_scheme_offset;
       
    54     u_int64_t custodian_ssp_offset;
       
    55     u_int64_t creation_time;
       
    56     u_int64_t creation_sequence;
       
    57     u_int64_t lifetime;
       
    58     u_int64_t dictionary_length;
       
    59     u_int64_t fragment_offset;
       
    60     u_int64_t original_length;
       
    61 };
       
    62 
       
    63 // Need quad versions of hton for manipulating full-length (unpacked) SDNV values
       
    64 
       
    65 #if defined(WORDS_BIGENDIAN) && (WORDS_BIGENDIAN == 1)
       
    66 #define htonq( x ) (x)
       
    67 #define ntohq( x ) (x)
       
    68 #else
       
    69 
       
    70 inline u_int64_t htonq( u_int64_t x )
       
    71 {
       
    72     u_int64_t   res;
       
    73     u_int32_t   hi = x >> 32;
       
    74     u_int32_t   lo = x & 0xffffffff;
       
    75     hi = htonl( hi );
       
    76     res = htonl( lo );
       
    77     res = res << 32 | hi;
       
    78 
       
    79     return res;
       
    80 }
       
    81 
       
    82 inline u_int64_t ntohq( u_int64_t x )
       
    83 {
       
    84     u_int64_t   res;
       
    85     u_int32_t   hi = x >> 32;
       
    86     u_int32_t   lo = x & 0xffffffff;
       
    87     hi = ntohl( hi );
       
    88     res = ntohl( lo );
       
    89     res = res << 32 | hi;
       
    90 
       
    91     return res;
       
    92 }
       
    93 #endif
       
    94 
       
    95 
       
    96 //----------------------------------------------------------------------
       
    97 Ciphersuite_PI2::Ciphersuite_PI2()
       
    98 {
       
    99 }
       
   100 
       
   101 //----------------------------------------------------------------------
       
   102 u_int16_t
       
   103 Ciphersuite_PI2::cs_num(void)
       
   104 {
       
   105     return CSNUM_PI2;
       
   106 }
       
   107 
       
   108 //----------------------------------------------------------------------
       
   109 int
       
   110 Ciphersuite_PI2::consume(Bundle*    bundle,
       
   111                          BlockInfo* block,
       
   112                          u_char*    buf,
       
   113                          size_t     len)
       
   114 {
       
   115     int cc = block->owner()->consume(bundle, block, buf, len);
       
   116 
       
   117     if (cc == -1) {
       
   118         return -1; // protocol error
       
   119     }
       
   120     
       
   121     
       
   122     // in on-the-fly scenario, process this data for those interested
       
   123     
       
   124     if (! block->complete()) {
       
   125         ASSERT(cc == (int)len);
       
   126         return cc;
       
   127     }
       
   128 
       
   129     if ( block->locals() == NULL ) {      // then we need to parse it
       
   130         parse(block);
       
   131     }
       
   132     
       
   133     return cc;
       
   134 }
       
   135 
       
   136 //----------------------------------------------------------------------
       
   137 bool
       
   138 Ciphersuite_PI2::validate(const Bundle*           bundle,
       
   139                           BlockInfoVec*           block_list,
       
   140                           BlockInfo*              block,
       
   141                           status_report_reason_t* reception_reason,
       
   142                           status_report_reason_t* deletion_reason)
       
   143 {
       
   144     (void)reception_reason;
       
   145 
       
   146     size_t          sdnv_len;
       
   147     u_char*         buf;
       
   148     size_t          len;
       
   149     size_t          digest_len;
       
   150     u_char          ps_digest[EVP_MAX_MD_SIZE];
       
   151      BP_Local_CS*    locals = NULL;
       
   152     u_int64_t       field_length;
       
   153     std::vector<u_int64_t>              correlator_list;
       
   154     std::vector<u_int64_t>::iterator    cl_iter;
       
   155     EndpointID      local_eid = BundleDaemon::instance()->local_eid();
       
   156     BlockInfoVec::iterator iter;
       
   157     u_int16_t       cs_flags;
       
   158     int             err = 0;
       
   159     DataBuffer      db;
       
   160         
       
   161     log_debug_p(log, "Ciphersuite_PI2::validate()");
       
   162     locals = dynamic_cast<BP_Local_CS*>(block->locals());
       
   163     CS_FAIL_IF_NULL(locals);
       
   164     cs_flags = locals->cs_flags();
       
   165     
       
   166     if ( destination_is_local_node(bundle, block) )
       
   167     {  //yes - this is ours so go to work
       
   168             
       
   169         if ( !(cs_flags & CS_BLOCK_HAS_RESULT) ) {
       
   170             log_err_p(log, "Ciphersuite_PI2::validate: block has no security_result");
       
   171             goto fail;
       
   172         }
       
   173         
       
   174         create_digest(bundle, block_list, block, db);   
       
   175         digest_len = db.len();
       
   176         memcpy(ps_digest, db.buf(), digest_len);     
       
   177 
       
   178         log_debug_p(log, "Ciphersuite_PI2::validate() digest      0x%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx",
       
   179                     ps_digest[0], ps_digest[1], ps_digest[2], ps_digest[3], ps_digest[4], ps_digest[5], ps_digest[6], ps_digest[7], ps_digest[8], ps_digest[9], ps_digest[10], 
       
   180                     ps_digest[11], ps_digest[12], ps_digest[13], ps_digest[14], ps_digest[15], ps_digest[16], ps_digest[17], ps_digest[18], ps_digest[19]);
       
   181 
       
   182         // get pieces from results -- should be just the signature
       
   183         buf = locals->security_result().buf();
       
   184         len = locals->security_result().len();
       
   185         
       
   186         log_debug_p(log, "Ciphersuite_PI2::validate() security result, len = %zu", len);
       
   187         while ( len > 0 ) {
       
   188             u_char item_type = *buf++;
       
   189             --len;
       
   190             sdnv_len = SDNV::decode(buf, len, &field_length);
       
   191             buf += sdnv_len;
       
   192             len -= sdnv_len;
       
   193             
       
   194             switch ( item_type ) {
       
   195             case CS_signature_field:
       
   196             {
       
   197                 log_debug_p(log, "Ciphersuite_PI2::validate() CS_signature_field item, len %llu", U64FMT(field_length));
       
   198                         
       
   199                 err = KeySteward::verify(bundle, buf, field_length, ps_digest, digest_len);
       
   200                 if ( err == 0 ) {
       
   201                     log_debug_p(log, "Ciphersuite_PI2::validate() -- KeySteward::verify() returned %d", err);
       
   202                     locals->set_proc_flag(CS_BLOCK_PASSED_VALIDATION | CS_BLOCK_COMPLETED_DO_NOT_FORWARD);
       
   203                 } else {
       
   204                     log_err_p(log, "Ciphersuite_PI2::validate: CS_signature_field validation failed");                      
       
   205                     goto fail;
       
   206                 }
       
   207                         
       
   208             }
       
   209             break;
       
   210                     
       
   211             default:    // deal with improper items
       
   212                 log_err_p(log, "Ciphersuite_PI2::validate: unexpected item type %d in security_result", item_type);
       
   213                 goto fail;
       
   214             }
       
   215             buf += field_length;
       
   216             len -= field_length;
       
   217         }
       
   218     } else
       
   219         locals->set_proc_flag(CS_BLOCK_DID_NOT_FAIL);   // not for here so we didn't check this block
       
   220         
       
   221     log_debug_p(log, "Ciphersuite_PI2::validate() done");
       
   222     
       
   223     return true;
       
   224     
       
   225     
       
   226     
       
   227  fail:    
       
   228     locals->set_proc_flag(CS_BLOCK_FAILED_VALIDATION | CS_BLOCK_COMPLETED_DO_NOT_FORWARD);
       
   229     *deletion_reason = BundleProtocol::REASON_SECURITY_FAILED;
       
   230     return false;
       
   231 }
       
   232 
       
   233 //----------------------------------------------------------------------
       
   234 int
       
   235 Ciphersuite_PI2::prepare(const Bundle*    bundle,
       
   236                          BlockInfoVec*    xmit_blocks,
       
   237                          const BlockInfo* source,
       
   238                          const LinkRef&   link,
       
   239                          list_owner_t     list)
       
   240 {
       
   241     (void)bundle;
       
   242     (void)link;
       
   243     
       
   244     int             result = BP_FAIL;
       
   245     u_int16_t       cs_flags = 0;
       
   246     BP_Local_CS*    locals = NULL;
       
   247     BP_Local_CS*    source_locals = NULL;
       
   248     EndpointID      local_eid = BundleDaemon::instance()->local_eid();
       
   249     BundleDaemon*   bd = BundleDaemon::instance();
       
   250     
       
   251 //XXXpl - fix this test
       
   252     if ( (source != NULL)  &&
       
   253          (dynamic_cast<BP_Local_CS*>(source->locals())->security_dest() == bd->local_eid().data()) ) {
       
   254         log_debug_p(log, "Ciphersuite_PI2::prepare() - not being forwarded");
       
   255         return BP_SUCCESS;     //it was for us so don't forward
       
   256     }
       
   257     
       
   258     BlockInfo       bi = BlockInfo(BundleProtocol::find_processor(BundleProtocol::PAYLOAD_SECURITY_BLOCK), source);     // NULL source is OK here
       
   259     
       
   260     // If this is a received block then there's not a lot to do yet.
       
   261     // We copy some parameters - the main work is done in generate().
       
   262     // Insertion is at the end of the list, which means that
       
   263     // it will be in the same position as received
       
   264     if ( list == BlockInfo::LIST_RECEIVED ) {
       
   265         
       
   266         if ( Ciphersuite::destination_is_local_node(bundle, source) )
       
   267             return BP_SUCCESS;     //don't forward if it's for here
       
   268 
       
   269         CS_FAIL_IF_NULL(source);
       
   270         xmit_blocks->push_back(bi);
       
   271         BlockInfo* bp = &(xmit_blocks->back());
       
   272         CS_FAIL_IF_NULL(bp);
       
   273         bp->set_eid_list(source->eid_list());
       
   274         log_debug_p(log, "Ciphersuite_PI2::prepare() - forward received block len %u eid_list_count %zu new count %zu",
       
   275                     source->full_length(), source->eid_list().size(), bp->eid_list().size());
       
   276         
       
   277         CS_FAIL_IF_NULL( source->locals() );      // broken
       
   278 
       
   279         source_locals = dynamic_cast<BP_Local_CS*>(source->locals());
       
   280         CS_FAIL_IF_NULL(source_locals);           // also broken
       
   281         bp->set_locals(new BP_Local_CS);
       
   282         locals = dynamic_cast<BP_Local_CS*>(bp->locals());
       
   283         CS_FAIL_IF_NULL(locals);
       
   284         locals->set_owner_cs_num(CSNUM_PI2);
       
   285         cs_flags = source_locals->cs_flags();
       
   286         locals->set_list_owner(BlockInfo::LIST_RECEIVED);
       
   287         locals->set_correlator(source_locals->correlator());
       
   288         bp->writable_contents()->reserve(source->full_length());
       
   289         bp->writable_contents()->set_len(0);
       
   290         
       
   291         // copy security-src and -dest if they exist
       
   292         if ( source_locals->cs_flags() & CS_BLOCK_HAS_SOURCE ) {
       
   293             CS_FAIL_IF(source_locals->security_src().length() == 0 );
       
   294             log_debug_p(log, "Ciphersuite_PI2::prepare() add security_src EID");
       
   295             cs_flags |= CS_BLOCK_HAS_SOURCE;
       
   296             locals->set_security_src(source_locals->security_src());
       
   297         }
       
   298         
       
   299         if ( source_locals->cs_flags() & CS_BLOCK_HAS_DEST ) {
       
   300             CS_FAIL_IF(source_locals->security_dest().length() == 0 );
       
   301             log_debug_p(log, "Ciphersuite_PI2::prepare() add security_dest EID");
       
   302             cs_flags |= CS_BLOCK_HAS_DEST;
       
   303             locals->set_security_dest(source_locals->security_dest());
       
   304         }
       
   305         locals->set_cs_flags(cs_flags);
       
   306         log_debug_p(log, "Ciphersuite_PI2::prepare() - inserted block eid_list_count %zu",
       
   307                     bp->eid_list().size());
       
   308         result = BP_SUCCESS;
       
   309         return result;
       
   310     } else {
       
   311 
       
   312         // initialize the block
       
   313         log_debug_p(log, "Ciphersuite_PI2::prepare() - add new block (or API block etc)");
       
   314         bi.set_locals(new BP_Local_CS);
       
   315         CS_FAIL_IF_NULL(bi.locals());
       
   316         locals = dynamic_cast<BP_Local_CS*>(bi.locals());
       
   317         CS_FAIL_IF_NULL(locals);
       
   318         locals->set_owner_cs_num(CSNUM_PI2);
       
   319         locals->set_list_owner(list);
       
   320         
       
   321         // if there is a security-src and/or -dest, use it -- might be specified by API
       
   322         if ( source != NULL && source->locals() != NULL)  {
       
   323             locals->set_security_src(dynamic_cast<BP_Local_CS*>(source->locals())->security_src());
       
   324             locals->set_security_dest(dynamic_cast<BP_Local_CS*>(source->locals())->security_dest());
       
   325         }
       
   326         
       
   327         log_debug_p(log, "Ciphersuite_PI2::prepare() local_eid %s bundle->source_ %s", local_eid.c_str(), bundle->source().c_str());
       
   328         // if not, and we didn't create the bundle, specify ourselves as sec-src
       
   329         if ( (locals->security_src().length() == 0) && (local_eid != bundle->source()))
       
   330             locals->set_security_src(local_eid.str());
       
   331         
       
   332         // if we now have one, add it to list, etc
       
   333         if ( locals->security_src().length() > 0 ) {
       
   334             log_debug_p(log, "Ciphersuite_PI2::prepare() add security_src EID %s", locals->security_src().c_str());
       
   335             cs_flags |= CS_BLOCK_HAS_SOURCE;
       
   336             bi.add_eid(locals->security_src());
       
   337         }
       
   338         
       
   339         if ( locals->security_dest().length() > 0 ) {
       
   340             log_debug_p(log, "Ciphersuite_PI2::prepare() add security_dest EID %s", locals->security_dest().c_str());
       
   341             cs_flags |= CS_BLOCK_HAS_DEST;
       
   342             bi.add_eid(locals->security_dest());
       
   343         }
       
   344             
       
   345         locals->set_cs_flags(cs_flags);
       
   346             
       
   347         // We should already have the primary block in the list.
       
   348         // We'll insert this after the primary and any BA blocks
       
   349         // and before everything else
       
   350         if ( xmit_blocks->size() > 0 ) {
       
   351             BlockInfoVec::iterator iter = xmit_blocks->begin();
       
   352             
       
   353             while ( iter != xmit_blocks->end()) {
       
   354                 switch (iter->type()) {
       
   355                 case BundleProtocol::PRIMARY_BLOCK:
       
   356                 case BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK:
       
   357                     ++iter;
       
   358                     continue;
       
   359                     
       
   360                 default:
       
   361                     break;
       
   362                 }
       
   363                 xmit_blocks->insert(iter, bi);
       
   364                 break;
       
   365             }
       
   366         } else {
       
   367             // it's weird if there are no other blocks but, oh well ...
       
   368             xmit_blocks->push_back(bi);
       
   369         }
       
   370     }
       
   371     
       
   372     result = BP_SUCCESS;
       
   373     return result;
       
   374     
       
   375  fail:
       
   376     if ( locals !=  NULL )
       
   377         locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
       
   378     return BP_FAIL;
       
   379 }
       
   380 
       
   381 //----------------------------------------------------------------------
       
   382 int
       
   383 Ciphersuite_PI2::generate(const Bundle*  bundle,
       
   384                           BlockInfoVec*  xmit_blocks,
       
   385                           BlockInfo*     block,
       
   386                           const LinkRef& link,
       
   387                           bool           last)
       
   388 {
       
   389     (void)bundle;
       
   390     (void)link;
       
   391     (void)xmit_blocks;
       
   392     
       
   393     int             result = BP_FAIL;
       
   394     size_t          sig_len = 0;
       
   395     size_t          res_len = 0;
       
   396     size_t          length = 0;
       
   397     size_t          param_len = 0;
       
   398     u_char          fragment_item[24];             // 24 is enough for 2 max-sized SDNVs and type and length
       
   399     u_int16_t       cs_flags = 0;
       
   400     BP_Local_CS*    locals = dynamic_cast<BP_Local_CS*>(block->locals());
       
   401     u_char*         ptr;
       
   402     size_t          temp;
       
   403     size_t          rem;
       
   404     DataBuffer      encrypted_key;
       
   405     EVP_MD_CTX      ctx;
       
   406     size_t          digest_len;
       
   407     u_char*         buf = NULL;
       
   408     
       
   409     int             sdnv_len = 0;       // use an int to handle -1 return values
       
   410     int             err = 0;
       
   411     int             len = 0;
       
   412     BlockInfo::DataBuffer* contents = NULL;
       
   413     LocalBuffer*    params = NULL;
       
   414         
       
   415     log_debug_p(log, "Ciphersuite_PI2::generate() %p", block);
       
   416     CS_FAIL_IF_NULL(locals);
       
   417     cs_flags = locals->cs_flags();      // get flags from prepare()
       
   418     // if this is a received block then it's easy
       
   419     if ( locals->list_owner() == BlockInfo::LIST_RECEIVED ) 
       
   420     {
       
   421         // generate the preamble and copy the data.
       
   422         size_t length = block->source()->data_length();
       
   423         
       
   424         generate_preamble(xmit_blocks, 
       
   425                           block,
       
   426                           BundleProtocol::PAYLOAD_SECURITY_BLOCK,
       
   427                           BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
       
   428                           (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
       
   429                           length);
       
   430 
       
   431         BlockInfo::DataBuffer* contents = block->writable_contents();
       
   432         contents->reserve(block->data_offset() + length);
       
   433         contents->set_len(block->data_offset() + length);
       
   434         memcpy(contents->buf() + block->data_offset(),
       
   435                block->source()->data(), length);
       
   436         log_debug_p(log, "Ciphersuite_PI2::generate() %p done", block);
       
   437         return BP_SUCCESS;
       
   438     }    /**************  forwarding done  **************/
       
   439     
       
   440     
       
   441     /* params field will contain
       
   442        - fragment offset and length, if a fragment-bundle, plus type and length
       
   443     */
       
   444 
       
   445     params = locals->writable_security_params();
       
   446     
       
   447     param_len = 0;
       
   448     
       
   449     if ( bundle->is_fragment() ) {
       
   450         log_debug_p(log, "Ciphersuite_PI2::generate() bundle is fragment");
       
   451         ptr = &fragment_item[2];
       
   452         rem = sizeof(fragment_item) - 2;
       
   453         temp = SDNV::encode(bundle->frag_offset(), ptr, rem);
       
   454         ptr += temp;
       
   455         rem -= temp;
       
   456         temp += SDNV::encode(bundle->payload().length(), ptr, rem);
       
   457         fragment_item[0] = CS_fragment_offset_and_length_field;
       
   458         fragment_item[1] = temp;    //guaranteed to fit as a "one-byte SDNV"
       
   459         param_len += 2 + temp;
       
   460         
       
   461     }
       
   462     
       
   463     if ( param_len > 0 ) {
       
   464         cs_flags |= CS_BLOCK_HAS_PARAMS;
       
   465         params->reserve(param_len); 
       
   466         params->set_len(param_len);
       
   467         log_debug_p(log, "Ciphersuite_PI2::generate() security params, len = %zu", param_len);
       
   468         
       
   469         ptr = params->buf();
       
   470         
       
   471         if ( bundle->is_fragment() ) 
       
   472             memcpy(ptr, fragment_item, 2 + temp);
       
   473     }
       
   474     
       
   475     // need to calculate the size of the security-result items,
       
   476     // and the total length of the combined field
       
   477     
       
   478     /*   result field will contain
       
   479          - signed hash, plus type and length
       
   480     */
       
   481     EVP_MD_CTX_init(&ctx);
       
   482     err = EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
       
   483     CS_FAIL_IF(err == 0);
       
   484     digest_len = EVP_MD_CTX_size(&ctx);
       
   485     EVP_MD_CTX_cleanup(&ctx);
       
   486     
       
   487     KeySteward::signature_length(bundle, NULL, link, digest_len, sig_len);
       
   488     
       
   489     res_len = 1 + SDNV::encoding_len(sig_len) + sig_len;
       
   490     
       
   491     // First we need to work out the lengths and create the preamble
       
   492     cs_flags |= CS_BLOCK_HAS_RESULT;
       
   493     locals->set_cs_flags(cs_flags);
       
   494     length = 0; 
       
   495     length += SDNV::encoding_len(CSNUM_PI2);
       
   496     length += SDNV::encoding_len(locals->cs_flags());
       
   497     
       
   498     param_len = locals->security_params().len();
       
   499     length += SDNV::encoding_len(param_len) + param_len;
       
   500     locals->set_security_result_offset(length);     //remember this for finalize()
       
   501     length += SDNV::encoding_len(res_len) + res_len;
       
   502         
       
   503     contents = block->writable_contents();
       
   504 
       
   505     generate_preamble(xmit_blocks, 
       
   506                       block,
       
   507                       BundleProtocol::PAYLOAD_SECURITY_BLOCK,
       
   508                       BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
       
   509                       (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
       
   510                       length);
       
   511     
       
   512 
       
   513     log_debug_p(log, "Ciphersuite_PI2::generate() preamble len %u block len %zu", block->data_offset(), length);
       
   514     contents->reserve(block->data_offset() + length);
       
   515     contents->set_len(block->data_offset() + length);
       
   516     buf = block->writable_contents()->buf() + block->data_offset();
       
   517     len = length;
       
   518     
       
   519     // Assemble data into block contents.
       
   520         
       
   521     // ciphersuite number and flags
       
   522     sdnv_len = SDNV::encode(locals->owner_cs_num(), buf, len);
       
   523     CS_FAIL_IF(sdnv_len <= 0);
       
   524     buf += sdnv_len;
       
   525     len -= sdnv_len;
       
   526     
       
   527     sdnv_len = SDNV::encode(locals->cs_flags(), buf, len);
       
   528     CS_FAIL_IF(sdnv_len <= 0);
       
   529     buf += sdnv_len;
       
   530     len -= sdnv_len;
       
   531             
       
   532     if ( param_len > 0 ) {
       
   533         // length of params
       
   534         sdnv_len = SDNV::encode(param_len, buf, len);
       
   535         CS_FAIL_IF(sdnv_len <= 0);
       
   536         buf += sdnv_len;
       
   537         len -= sdnv_len;
       
   538         
       
   539         // params data
       
   540         memcpy(buf, locals->security_params().buf(), param_len );
       
   541         buf += param_len;
       
   542         len -= param_len;
       
   543     }
       
   544 
       
   545     // length of result -- we have to put this in now
       
   546     sdnv_len = SDNV::encode(res_len, buf, len);
       
   547 
       
   548     
       
   549     //  no, no ! Not yet !!    
       
   550     //  ASSERT( len == 0 );
       
   551     log_debug_p(log, "Ciphersuite_PI2::generate() done");
       
   552         
       
   553 
       
   554     result = BP_SUCCESS;
       
   555     return result;
       
   556 
       
   557  fail:
       
   558     if ( locals !=  NULL )
       
   559         locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
       
   560     return BP_FAIL;
       
   561 }
       
   562 
       
   563 //----------------------------------------------------------------------
       
   564 int
       
   565 Ciphersuite_PI2::finalize(const Bundle*  bundle, 
       
   566                           BlockInfoVec*  xmit_blocks,
       
   567                           BlockInfo*     block, 
       
   568                           const LinkRef& link)
       
   569 {
       
   570     (void)link;
       
   571     int             result = BP_FAIL;
       
   572     size_t          len;
       
   573     size_t          sdnv_len;
       
   574     size_t          res_len;
       
   575     u_char*         buf;
       
   576     BP_Local_CS*    locals = NULL;
       
   577     std::vector<u_int64_t>              correlator_list;
       
   578     std::vector<u_int64_t>::iterator    cl_iter;
       
   579     EndpointID      local_eid = BundleDaemon::instance()->local_eid();
       
   580     BlockInfoVec::iterator iter;
       
   581     DataBuffer      db_digest;
       
   582     DataBuffer      db_signed;
       
   583     int             err = 0;
       
   584     BlockInfo::DataBuffer* contents = NULL;
       
   585     LocalBuffer*    digest_result = NULL;
       
   586     size_t          sig_len = 0;
       
   587         
       
   588     log_debug_p(log, "Ciphersuite_PI2::finalize()");
       
   589     locals = dynamic_cast<BP_Local_CS*>(block->locals());
       
   590     CS_FAIL_IF_NULL(locals);
       
   591         
       
   592     // if this is a received block then we're done
       
   593     if ( locals->list_owner() == BlockInfo::LIST_RECEIVED ) 
       
   594         return BP_SUCCESS;
       
   595     
       
   596     create_digest(bundle, xmit_blocks, block, db_digest);        
       
   597     
       
   598     err = KeySteward::sign(bundle, NULL, link, db_digest, db_signed);
       
   599     CS_FAIL_IF(err != 0);
       
   600     sig_len = db_signed.len();
       
   601     res_len = 1 + SDNV::encoding_len(sig_len) + sig_len;
       
   602     
       
   603     // build the result item
       
   604     digest_result = locals->writable_security_result();
       
   605     digest_result->reserve(res_len);
       
   606     digest_result->set_len(res_len);
       
   607     
       
   608     buf = digest_result->buf();
       
   609     len = digest_result->len();
       
   610     
       
   611     *buf++ = Ciphersuite::CS_signature_field;               // item type
       
   612     len--;
       
   613     
       
   614     sdnv_len = SDNV::encode(sig_len, buf, len);
       
   615     buf += sdnv_len;
       
   616     len -= sdnv_len;
       
   617     
       
   618     memcpy(buf, db_signed.buf(), sig_len);
       
   619     
       
   620     
       
   621     // now put the result item into the block contents
       
   622     contents = block->writable_contents();
       
   623     buf = contents->buf();
       
   624     len = contents->len();
       
   625     buf += block->data_offset();    // we need to add data_offset as well,
       
   626     len -= block->data_offset();    // since we're pointing at the whole buffer
       
   627     
       
   628     buf += locals->security_result_offset();    //and this offset is just within
       
   629     len -= locals->security_result_offset();    //the data portion of the buffer
       
   630     sdnv_len = SDNV::len(buf);  // size of result-length field
       
   631     buf += sdnv_len;            // step over that length field
       
   632     len -= sdnv_len;
       
   633     memcpy(buf, digest_result->buf(), digest_result->len());
       
   634     log_debug_p(log, "Ciphersuite_PI2::finalize() done");
       
   635     
       
   636     result = BP_SUCCESS;
       
   637     return result;
       
   638 
       
   639  fail:
       
   640     if ( locals !=  NULL )
       
   641         locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
       
   642     return BP_FAIL;
       
   643 }
       
   644 
       
   645 //----------------------------------------------------------------------
       
   646 void
       
   647 Ciphersuite_PI2::digest(const Bundle*    bundle,
       
   648                         const BlockInfo* caller_block,
       
   649                         const BlockInfo* target_block,
       
   650                         const void*      buf,
       
   651                         size_t           len,
       
   652                         OpaqueContext*   r)
       
   653 {
       
   654     (void)bundle;
       
   655     (void)caller_block;
       
   656     (void)target_block;
       
   657     log_debug_p(log, "Ciphersuite_PI2::digest() %zu bytes", len);
       
   658     
       
   659     EVP_MD_CTX*       pctx = reinterpret_cast<EVP_MD_CTX*>(r);
       
   660     
       
   661     EVP_DigestUpdate( pctx, buf, len );
       
   662 }
       
   663 
       
   664 //----------------------------------------------------------------------
       
   665 void
       
   666 Ciphersuite_PI2::create_digest(const Bundle*  bundle, 
       
   667                                BlockInfoVec*  block_list,
       
   668                                BlockInfo*     block,
       
   669                                DataBuffer&    db)
       
   670 {
       
   671     size_t          len;
       
   672     size_t          sdnv_len;
       
   673     EVP_MD_CTX      ctx;
       
   674     OpaqueContext*  r = reinterpret_cast<OpaqueContext*>(&ctx);
       
   675     char*           dict;
       
   676     u_int32_t       offset;
       
   677     u_char*         buf;
       
   678     const char*     ptr;
       
   679     size_t          plen;
       
   680     size_t          digest_len;
       
   681     u_char          ps_digest[EVP_MAX_MD_SIZE];
       
   682     u_int32_t       rlen = 0;
       
   683     u_int32_t       header_len;
       
   684     u_char          c;
       
   685     u_int64_t       eid_ref_count = 0LLU;
       
   686     BP_Local_CS*    locals = NULL;
       
   687     BP_Local_CS*    target_locals = NULL;
       
   688     u_int64_t       target_flags;
       
   689     u_int64_t       flags_save;
       
   690     u_int64_t       mask = 0LLU;            /// specify mask for flags
       
   691     u_int64_t       mask_primary = 0LLU;    /// mask for primary-block flags
       
   692     u_int64_t       target_content_length;
       
   693     u_int64_t       correlator;
       
   694     u_int64_t       cs_flags;
       
   695     u_int64_t       suite_num;
       
   696     std::vector<u_int64_t>              correlator_list;
       
   697     std::vector<u_int64_t>::iterator    cl_iter;
       
   698     EndpointID      local_eid = BundleDaemon::instance()->local_eid();
       
   699     BlockInfoVec::iterator iter;
       
   700     int             err = 0;
       
   701     PrimaryBlock_ex primary;
       
   702         
       
   703     log_debug_p(log, "Ciphersuite_PI2::create_digest()");
       
   704     locals = dynamic_cast<BP_Local_CS*>(block->locals());
       
   705         
       
   706     // prepare context 
       
   707     EVP_MD_CTX_init(&ctx);
       
   708     err = EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL);
       
   709     digest_len = EVP_MD_CTX_size(&ctx);
       
   710     // XXX-pl  check error -- zero is failure
       
   711         
       
   712     // Walk the list and process each of the blocks.
       
   713     // We only digest PS, C3 and the payload data,
       
   714     // all others are ignored
       
   715     
       
   716     // Note that we can only process PSBs and C3s that follow this block
       
   717     // as doing otherwise would mean that there would be a
       
   718     // correlator block preceding its parent
       
   719     
       
   720     // There can also be tunnelling issues, depending upon the
       
   721     // exact sequencing of blocks. It seems best to add C blocks
       
   722     // as early as possible in order to mitigate this problem.
       
   723     // That has its own drawbacks unfortunately
       
   724     
       
   725     header_len =        1       //version
       
   726                         +   8       //flags SDNV
       
   727                         +   4       //header length itself
       
   728                         +   4       //destination eid length
       
   729                         +   4       //source eid length
       
   730                         +   4       //report-to eid length
       
   731                         +   8       //creation SDNV #1
       
   732                         +   8       //creation SDNV #2
       
   733                         +   8;      //lifetime SDNV
       
   734     
       
   735     if ( bundle->is_fragment() ) 
       
   736         header_len +=   8       //fragment offset SDNV
       
   737                         +   8;      //total-length SDNV
       
   738     
       
   739     // do stuff for primary, and ignore it during the walk
       
   740     
       
   741     iter = block_list->begin();     //primary
       
   742     
       
   743     err = read_primary(bundle, &*iter, primary, &dict);
       
   744     
       
   745     header_len += strlen(dict + primary.dest_scheme_offset);
       
   746     header_len += strlen(dict + primary.dest_ssp_offset);
       
   747     header_len += strlen(dict + primary.source_scheme_offset);
       
   748     header_len += strlen(dict + primary.source_ssp_offset);
       
   749     header_len += strlen(dict + primary.replyto_scheme_offset);
       
   750     header_len += strlen(dict + primary.replyto_ssp_offset);
       
   751     log_debug_p(log, "Ciphersuite_PI2::create_digest() header_len %u", header_len);     
       
   752 
       
   753 
       
   754     // Now start the actual digest process
       
   755     digest( bundle, block, &*iter, &primary.version, 1, r);     //version
       
   756     
       
   757     primary.processing_flags &= mask_primary;
       
   758     target_flags = htonq(primary.processing_flags);
       
   759     digest( bundle, block, &*iter, &primary.processing_flags, sizeof(primary.processing_flags), r);
       
   760     
       
   761     header_len = htonl(header_len);
       
   762     digest( bundle, block, &*iter, &header_len, sizeof(header_len), r);
       
   763     
       
   764     
       
   765     offset = strlen(dict + primary.dest_scheme_offset) + strlen(dict + primary.dest_ssp_offset);    // Note:- "offset" is 4 bytes, not 8
       
   766     offset = htonl(offset);
       
   767     digest( bundle, block, &*iter, &offset, sizeof(offset), r);
       
   768     digest( bundle, block, &*iter, dict + primary.dest_scheme_offset, strlen(dict + primary.dest_scheme_offset), r);
       
   769     digest( bundle, block, &*iter, dict + primary.dest_ssp_offset, strlen(dict + primary.dest_ssp_offset), r);
       
   770 
       
   771     offset = strlen(dict + primary.source_scheme_offset) + strlen(dict + primary.source_ssp_offset);
       
   772     offset = htonl(offset);
       
   773     digest( bundle, block, &*iter, &offset, sizeof(offset), r);
       
   774     digest( bundle, block, &*iter, dict + primary.source_scheme_offset, strlen(dict + primary.source_scheme_offset), r);
       
   775     digest( bundle, block, &*iter, dict + primary.source_ssp_offset, strlen(dict + primary.source_ssp_offset), r);
       
   776 
       
   777     offset = strlen(dict + primary.replyto_scheme_offset) + strlen(dict + primary.replyto_ssp_offset);
       
   778     offset = htonl(offset);
       
   779     digest( bundle, block, &*iter, &offset, sizeof(offset), r);
       
   780     digest( bundle, block, &*iter, dict + primary.replyto_scheme_offset, strlen(dict + primary.replyto_scheme_offset), r);
       
   781     digest( bundle, block, &*iter, dict + primary.replyto_ssp_offset, strlen(dict + primary.replyto_ssp_offset), r);
       
   782     
       
   783     // two SDNVs for creation timestamp, one for lifetime
       
   784     primary.creation_time = htonq(primary.creation_time);
       
   785     digest( bundle, block, &*iter, &primary.creation_time, sizeof(primary.creation_time), r);
       
   786     primary.creation_sequence = htonq(primary.creation_sequence);
       
   787     digest( bundle, block, &*iter, &primary.creation_sequence, sizeof(primary.creation_sequence), r);
       
   788     primary.lifetime = htonq(primary.lifetime);
       
   789     digest( bundle, block, &*iter, &primary.lifetime, sizeof(primary.lifetime), r);
       
   790     
       
   791     if ( bundle->is_fragment() ) {
       
   792         primary.fragment_offset = htonq(primary.fragment_offset);
       
   793         digest( bundle, block, &*iter, &primary.fragment_offset, sizeof(primary.fragment_offset), r);
       
   794         primary.original_length = htonq(primary.original_length);
       
   795         digest( bundle, block, &*iter, &primary.original_length, sizeof(primary.original_length), r);
       
   796     }
       
   797     
       
   798     ++iter;     //primary is done now
       
   799     
       
   800     log_debug_p(log, "Ciphersuite_PI2::create_digest() walk block list");
       
   801     for ( ;
       
   802           iter != block_list->end();
       
   803           ++iter)
       
   804     {
       
   805         // Advance the iterator to our current position.
       
   806         // While we do it, we also remember the correlator values
       
   807         // of any PSBs or C3 blocks we encounter.
       
   808         // We do this to avoid processing any related correlated blocks
       
   809         // Note that we include the current block in the test below
       
   810         // in order to prevent encapsulating it !!
       
   811         target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
       
   812         if ( (&*iter) <= block ) {
       
   813             if (  iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK ||
       
   814                   (iter->type() == BundleProtocol::CONFIDENTIALITY_BLOCK  &&
       
   815                    target_locals->owner_cs_num() == Ciphersuite_PC3::CSNUM_PC3  )  ) {
       
   816                 if ( target_locals->cs_flags() & CS_BLOCK_HAS_CORRELATOR) {
       
   817                     //add correlator to exclude-list
       
   818                     correlator_list.push_back(target_locals->correlator());
       
   819                 }
       
   820             }
       
   821             continue;
       
   822         }
       
   823         
       
   824         
       
   825         switch ( iter->type() ) {
       
   826         case BundleProtocol::PAYLOAD_SECURITY_BLOCK:
       
   827         case BundleProtocol::CONFIDENTIALITY_BLOCK:
       
   828         {
       
   829                     
       
   830             log_debug_p(log, "Ciphersuite_PI2::create_digest() PS or C block type %d cs_num %d",
       
   831                         iter->type(), target_locals->owner_cs_num());
       
   832             if (  iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK  &&
       
   833                   target_locals->owner_cs_num() != Ciphersuite_PC3::CSNUM_PC3 )  
       
   834                 continue;       // only digest C3
       
   835                     
       
   836                     
       
   837             // see if there's a correlator and, if there is,
       
   838             // if this is a secondary block. Only process a secondary
       
   839             // if we also did its primary
       
   840             bool    skip_target = false;
       
   841             target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
       
   842             log_debug_p(log, "Ciphersuite_PI2::create_digest() target_locals->cs_flags 0x%hx", target_locals->cs_flags());
       
   843             log_debug_p(log, "Ciphersuite_PI2::create_digest() target_locals->correlator() 0x%llx", U64FMT(target_locals->correlator()));
       
   844             if ( target_locals->cs_flags() & CS_BLOCK_HAS_CORRELATOR) {
       
   845                 correlator = target_locals->correlator();
       
   846                 for ( cl_iter = correlator_list.begin();
       
   847                       cl_iter < correlator_list.end();
       
   848                       ++cl_iter) {
       
   849                     if ( correlator == *cl_iter) {                              
       
   850                         skip_target = true;
       
   851                         break;      //break from for-loop
       
   852                     }
       
   853                 }
       
   854                 if ( skip_target )
       
   855                     break;  //break from switch, continue for "for" loop
       
   856                         
       
   857             }
       
   858                     
       
   859             log_debug_p(log, "Ciphersuite_PI2::create_digest() digest this block, len %u eid_list().size() %zu", 
       
   860                         iter->full_length(), iter->eid_list().size());
       
   861             // Either it has no correlator, or it wasn't in the list.
       
   862             // So we will process it in the digest
       
   863                     
       
   864             /**********  start preamble processing  **********/
       
   865             buf = iter->contents().buf();
       
   866             len = iter->full_length();
       
   867                     
       
   868                     
       
   869             // Process block type
       
   870             c = *buf++;
       
   871             len--;
       
   872             digest( bundle, block, &*iter, &c, 1, r);
       
   873                     
       
   874             // Process flags
       
   875             sdnv_len = SDNV::decode( buf, len, &target_flags);
       
   876             buf += sdnv_len;
       
   877             len -= sdnv_len;
       
   878                     
       
   879             flags_save = target_flags;
       
   880             target_flags &= mask;
       
   881             target_flags = htonq(target_flags);
       
   882             digest( bundle, block, &*iter, &target_flags, sizeof(target_flags), r);
       
   883                     
       
   884             // EID list is next, starting with the count although we don't digest it
       
   885             if ( flags_save & BundleProtocol::BLOCK_FLAG_EID_REFS ) {                    
       
   886                 sdnv_len = SDNV::decode(buf, len, &eid_ref_count);
       
   887                 buf += sdnv_len;
       
   888                 len -= sdnv_len;
       
   889                 log_debug_p(log, "Ciphersuite_PI2::create_digest() eid_ref_count %llu", U64FMT(eid_ref_count));
       
   890                                                 
       
   891                 // each ref is a pair of SDNVs, so process 2 * eid_ref_count text pieces
       
   892                 if ( eid_ref_count > 0 ) {
       
   893                     for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) {
       
   894                         sdnv_len = SDNV::decode(buf, len, &offset);
       
   895                         buf += sdnv_len;
       
   896                         len -= sdnv_len;
       
   897                                 
       
   898                         ptr = dict + offset;    //point at item in dictionary
       
   899                         plen = strlen(ptr);     // length *without* NULL-terminator
       
   900                         digest( bundle, block, &*iter, ptr, plen, r);
       
   901                     }
       
   902                 }       
       
   903             }
       
   904 
       
   905             // Process data length
       
   906             sdnv_len = SDNV::decode(buf, len, &target_content_length);
       
   907             buf += sdnv_len;
       
   908             len -= sdnv_len;
       
   909                     
       
   910             target_content_length = htonq(target_content_length);
       
   911             digest( bundle, block, &*iter, &target_content_length, sizeof(target_content_length), r);
       
   912                     
       
   913             // start of data is where to start main digest
       
   914             offset = buf - iter->contents().buf();
       
   915             ASSERT(offset == iter->data_offset());
       
   916             /**********  end of preamble processing  **********/
       
   917                     
       
   918                     
       
   919             /**********  start content processing  **********/
       
   920                     
       
   921             // if it's the current block, we have to exclude security-result data.
       
   922             // Note that security-result-length *is* included
       
   923             if ( (&*iter) == block ) {
       
   924 
       
   925                 // ciphersuite number and flags
       
   926                 sdnv_len = SDNV::decode(buf,
       
   927                                         len,
       
   928                                         &suite_num);
       
   929                 buf += sdnv_len;
       
   930                 len -= sdnv_len;
       
   931 
       
   932                 sdnv_len = SDNV::decode(buf,
       
   933                                         len,
       
   934                                         &cs_flags);
       
   935                 buf += sdnv_len;
       
   936                 len -= sdnv_len;
       
   937                         
       
   938                 if ( cs_flags & CS_BLOCK_HAS_RESULT ) {
       
   939                     // if there's a security-result we have to ease up to it
       
   940                     if ( cs_flags & CS_BLOCK_HAS_CORRELATOR )
       
   941                         buf += SDNV::len(buf);      //step over correlator
       
   942                             
       
   943                     if ( cs_flags & CS_BLOCK_HAS_PARAMS )
       
   944                         buf += SDNV::len(buf);      //step over params
       
   945                             
       
   946                     if ( cs_flags & CS_BLOCK_HAS_RESULT ) {
       
   947                         sdnv_len = SDNV::decode(buf, len, &target_content_length);
       
   948                         buf += sdnv_len;
       
   949                         len -= sdnv_len;
       
   950                         buf += SDNV::len(buf);      //step over security-result-length field
       
   951                     }
       
   952                             
       
   953                     len = buf - iter->contents().buf();  //this is the length to use
       
   954                 }
       
   955                 // now set buf back to the start of the content
       
   956                 buf = iter->contents().buf();
       
   957             }
       
   958                     
       
   959             iter->owner()->process( Ciphersuite_PI2::digest,
       
   960                                     bundle,
       
   961                                     block,
       
   962                                     &*iter,
       
   963                                     offset,
       
   964                                     len,
       
   965                                     r);
       
   966             /**********  end of content processing  **********/
       
   967             log_debug_p(log, "Ciphersuite_PI2::create_digest() digest done %p", &*iter);
       
   968 
       
   969         }
       
   970         break;  //break from switch, continue for "for" loop
       
   971             
       
   972         case BundleProtocol::PAYLOAD_BLOCK:
       
   973         {
       
   974                     
       
   975             /**********  start preamble processing  **********/
       
   976             buf = iter->contents().buf();
       
   977             len = iter->full_length();
       
   978                     
       
   979                     
       
   980             // Process block type
       
   981             c = *buf++;
       
   982             len--;
       
   983             digest( bundle, block, &*iter, &c, 1, r);
       
   984                     
       
   985             // Process flags
       
   986             sdnv_len = SDNV::decode( buf, len, &target_flags);
       
   987             buf += sdnv_len;
       
   988             len -= sdnv_len;
       
   989                                         
       
   990             flags_save = target_flags;
       
   991             target_flags &= mask;
       
   992             target_flags = htonq(target_flags);
       
   993             digest( bundle, block, &*iter, &target_flags, sizeof(target_flags), r);
       
   994                     
       
   995             // EID list is next, starting with the count although we don't digest it
       
   996             if ( flags_save & BundleProtocol::BLOCK_FLAG_EID_REFS ) {                    
       
   997                 sdnv_len = SDNV::decode(buf, len, &eid_ref_count);
       
   998                 buf += sdnv_len;
       
   999                 len -= sdnv_len;
       
  1000                                                 
       
  1001                 // each ref is a pair of SDNVs, so process 2 * eid_ref_count text pieces
       
  1002                 if ( eid_ref_count > 0 ) {
       
  1003                     for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) {
       
  1004                         sdnv_len = SDNV::decode(buf, len, &offset);
       
  1005                         buf += sdnv_len;
       
  1006                         len -= sdnv_len;
       
  1007                                 
       
  1008                         ptr = dict + offset;    //point at item in dictionary
       
  1009                         plen = strlen(ptr);     // length *without* NULL-terminator
       
  1010                         digest( bundle, block, &*iter, ptr, plen, r);
       
  1011                     }
       
  1012                 }       
       
  1013             }
       
  1014 
       
  1015             // Process data length
       
  1016             sdnv_len = SDNV::decode(buf, len, &target_content_length);
       
  1017             buf += sdnv_len;
       
  1018             len -= sdnv_len;
       
  1019                     
       
  1020             target_content_length = htonq(target_content_length);
       
  1021             digest( bundle, block, &*iter, &target_content_length, sizeof(target_content_length), r);
       
  1022                     
       
  1023             // start of data is where to start main digest
       
  1024             offset = buf - iter->contents().buf();
       
  1025             ASSERT(offset == iter->data_offset());
       
  1026             /**********  end of preamble processing  **********/
       
  1027                     
       
  1028             /**********  start content processing  **********/
       
  1029                                         
       
  1030             iter->owner()->process( Ciphersuite_PI2::digest,
       
  1031                                     bundle,
       
  1032                                     block,
       
  1033                                     &*iter,
       
  1034                                     offset,
       
  1035                                     len,
       
  1036                                     r);
       
  1037             /**********  end of content processing  **********/
       
  1038             log_debug_p(log, "Ciphersuite_PI2::create_digest() PAYLOAD_BLOCK done");
       
  1039         }
       
  1040         break;  //break from switch, continue for "for" loop
       
  1041                 
       
  1042         default:
       
  1043             continue;
       
  1044         
       
  1045         }   // end of switch  
       
  1046     }       // end of loop-through-all-the-blocks
       
  1047     
       
  1048     
       
  1049     err = EVP_DigestFinal_ex(&ctx, ps_digest, &rlen);
       
  1050     // XXX-pl  check error -- zero is failure
       
  1051     
       
  1052     log_debug_p(log, "Ciphersuite_PI2::create_digest() digest      0x%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx",
       
  1053                 ps_digest[0], ps_digest[1], ps_digest[2], ps_digest[3], ps_digest[4], ps_digest[5], ps_digest[6], ps_digest[7], ps_digest[8], ps_digest[9], ps_digest[10], 
       
  1054                 ps_digest[11], ps_digest[12], ps_digest[13], ps_digest[14], ps_digest[15], ps_digest[16], ps_digest[17], ps_digest[18], ps_digest[19]);
       
  1055 
       
  1056     EVP_MD_CTX_cleanup(&ctx);
       
  1057     
       
  1058     db.reserve(digest_len);
       
  1059     db.set_len(digest_len);
       
  1060     memcpy(db.buf(), ps_digest, digest_len);
       
  1061     
       
  1062     log_debug_p(log, "Ciphersuite_PI2::create_digest() done");
       
  1063     
       
  1064 }
       
  1065 
       
  1066 
       
  1067 //----------------------------------------------------------------------
       
  1068 int
       
  1069 Ciphersuite_PI2::read_primary(const Bundle*    bundle, 
       
  1070                               BlockInfo*       block,
       
  1071                               PrimaryBlock_ex& primary,
       
  1072                               char**           dict)
       
  1073 {
       
  1074     u_char*         buf;
       
  1075     size_t          len;
       
  1076 
       
  1077     size_t primary_len = block->full_length();
       
  1078 
       
  1079     buf = block->writable_contents()->buf();
       
  1080     len = block->writable_contents()->len();
       
  1081 
       
  1082     ASSERT(primary_len == len);
       
  1083 
       
  1084     primary.version = *(u_int8_t*)buf;
       
  1085     buf += 1;
       
  1086     len -= 1;
       
  1087     
       
  1088     if (primary.version != BundleProtocol::CURRENT_VERSION) {
       
  1089         log_warn_p(log, "protocol version mismatch %d != %d",
       
  1090                    primary.version, BundleProtocol::CURRENT_VERSION);
       
  1091         return -1;
       
  1092     }
       
  1093     
       
  1094 #define PBP_READ_SDNV(location) { \
       
  1095     int sdnv_len = SDNV::decode(buf, len, location); \
       
  1096     if (sdnv_len < 0) \
       
  1097         goto tooshort; \
       
  1098     buf += sdnv_len; \
       
  1099     len -= sdnv_len; }
       
  1100     
       
  1101     // Grab the SDNVs representing the flags and the block length.
       
  1102     PBP_READ_SDNV(&primary.processing_flags);
       
  1103     PBP_READ_SDNV(&primary.block_length);
       
  1104 
       
  1105     log_debug_p(log, "parsed primary block: version %d length %u",
       
  1106                 primary.version, block->data_length());    
       
  1107     
       
  1108 /*
       
  1109  * it may be that the ASSERT which follows is not appropriate because we're doing this
       
  1110  * on the outbound side and it seems that data_length() is the same as full_length().
       
  1111  * But what's remaining should be the same as what is promised.
       
  1112  log_debug_p(log, "parsed primary block: version %d length %u full_length %u len remaining %zu",
       
  1113  primary.version, block->data_length(), block->full_length(), len);    
       
  1114  // What remains in the buffer should now be equal to what the block-length
       
  1115  // field advertised.
       
  1116  ASSERT(len == block->data_length());
       
  1117 */
       
  1118     ASSERT(len == primary.block_length);
       
  1119     
       
  1120     // Read the various SDNVs up to the start of the dictionary.
       
  1121     PBP_READ_SDNV(&primary.dest_scheme_offset);
       
  1122     PBP_READ_SDNV(&primary.dest_ssp_offset);
       
  1123     PBP_READ_SDNV(&primary.source_scheme_offset);
       
  1124     PBP_READ_SDNV(&primary.source_ssp_offset);
       
  1125     PBP_READ_SDNV(&primary.replyto_scheme_offset);
       
  1126     PBP_READ_SDNV(&primary.replyto_ssp_offset);
       
  1127     PBP_READ_SDNV(&primary.custodian_scheme_offset);
       
  1128     PBP_READ_SDNV(&primary.custodian_ssp_offset);
       
  1129     PBP_READ_SDNV(&primary.creation_time);
       
  1130     PBP_READ_SDNV(&primary.creation_sequence);
       
  1131     PBP_READ_SDNV(&primary.lifetime);
       
  1132     PBP_READ_SDNV(&primary.dictionary_length);
       
  1133     *dict = reinterpret_cast<char*>(buf);
       
  1134     if (bundle->is_fragment()) {
       
  1135         PBP_READ_SDNV(&primary.fragment_offset);
       
  1136         PBP_READ_SDNV(&primary.original_length);
       
  1137     }
       
  1138 #undef PBP_READ_SDNV
       
  1139     return 0;
       
  1140     
       
  1141  tooshort:
       
  1142     return -1;
       
  1143 }
       
  1144 
       
  1145 
       
  1146 } // namespace dtn
       
  1147 
       
  1148 #endif /* BSP_ENABLED */