CryptoBuiltInImpl.cpp

Go to the documentation of this file.
00001 /*
00002  * Distributed under the OpenDDS License.
00003  * See: http://www.opendds.org/license.html
00004  */
00005 
00006 #include "CryptoBuiltInImpl.h"
00007 
00008 #include "CryptoBuiltInTypeSupportImpl.h"
00009 #include "CommonUtilities.h"
00010 #include "TokenWriter.h"
00011 
00012 #include "SSL/Utils.h"
00013 
00014 #include "dds/DdsDcpsInfrastructureC.h"
00015 #include "dds/DdsSecurityParamsC.h"
00016 
00017 #include "dds/DCPS/GuidUtils.h"
00018 #include "dds/DCPS/Message_Block_Ptr.h"
00019 #include "dds/DCPS/Serializer.h"
00020 
00021 #include "dds/DCPS/RTPS/MessageTypes.h"
00022 #include "dds/DCPS/RTPS/RtpsCoreTypeSupportImpl.h"
00023 
00024 #include <openssl/err.h>
00025 #include <openssl/evp.h>
00026 #include <openssl/rand.h>
00027 
00028 #include "OpenSSL_init.h"
00029 #include "OpenSSL_legacy.h" // Must come after all other OpenSSL includes
00030 
00031 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00032 
00033 using namespace DDS::Security;
00034 using OpenDDS::DCPS::Serializer;
00035 using OpenDDS::DCPS::Message_Block_Ptr;
00036 
00037 namespace OpenDDS {
00038 namespace Security {
00039 
00040 CryptoBuiltInImpl::CryptoBuiltInImpl()
00041   : mutex_()
00042   , next_handle_(1)
00043 {
00044   openssl_init();
00045 }
00046 
00047 CryptoBuiltInImpl::~CryptoBuiltInImpl()
00048 {
00049   openssl_cleanup();
00050 }
00051 
00052 bool CryptoBuiltInImpl::_is_a(const char* id)
00053 {
00054   return CryptoKeyFactory::_is_a(id)
00055     || CryptoKeyExchange::_is_a(id)
00056     || CryptoTransform::_is_a(id);
00057 }
00058 
00059 const char* CryptoBuiltInImpl::_interface_repository_id() const
00060 {
00061   return "";
00062 }
00063 
00064 bool CryptoBuiltInImpl::marshal(TAO_OutputCDR&)
00065 {
00066   return false;
00067 }
00068 
00069 NativeCryptoHandle CryptoBuiltInImpl::generate_handle()
00070 {
00071   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00072   return CommonUtilities::increment_handle(next_handle_);
00073 }
00074 
00075 
00076 // Key Factory
00077 
00078 namespace {
00079   const unsigned int KEY_LEN_BYTES = 32;
00080   const unsigned int BLOCK_LEN_BYTES = 16;
00081   const unsigned int MAX_BLOCKS_PER_SESSION = 1024;
00082 
00083   KeyMaterial_AES_GCM_GMAC make_key(unsigned int key_id, bool encrypt)
00084   {
00085     KeyMaterial_AES_GCM_GMAC k;
00086 
00087     for (unsigned int i = 0; i < TransformKindIndex; ++i) {
00088       k.transformation_kind[i] = 0;
00089     }
00090     k.transformation_kind[TransformKindIndex] =
00091       encrypt ? CRYPTO_TRANSFORMATION_KIND_AES256_GCM
00092       : CRYPTO_TRANSFORMATION_KIND_AES256_GMAC;
00093 
00094     k.master_salt.length(KEY_LEN_BYTES);
00095     RAND_bytes(k.master_salt.get_buffer(), KEY_LEN_BYTES);
00096 
00097     for (unsigned int i = 0; i < sizeof k.sender_key_id; ++i) {
00098       k.sender_key_id[i] = key_id >> (8 * i);
00099     }
00100 
00101     k.master_sender_key.length(KEY_LEN_BYTES);
00102     RAND_bytes(k.master_sender_key.get_buffer(), KEY_LEN_BYTES);
00103 
00104     for (unsigned int i = 0; i < sizeof k.receiver_specific_key_id; ++i) {
00105       k.receiver_specific_key_id[i] = 0;
00106     }
00107 
00108     k.master_receiver_specific_key.length(0);
00109     return k;
00110   }
00111 
00112   template <typename T, typename TSeq>
00113   void push_back(TSeq& seq, const T& t)
00114   {
00115     const unsigned int i = seq.length();
00116     seq.length(i + 1);
00117     seq[i] = t;
00118   }
00119 }
00120 
00121 ParticipantCryptoHandle CryptoBuiltInImpl::register_local_participant(
00122   IdentityHandle participant_identity,
00123   PermissionsHandle participant_permissions,
00124   const DDS::PropertySeq&,
00125   const ParticipantSecurityAttributes& participant_security_attributes,
00126   SecurityException& ex)
00127 {
00128   if (DDS::HANDLE_NIL == participant_identity) {
00129     CommonUtilities::set_security_error(ex, -1, 0, "Invalid local participant ID");
00130     return DDS::HANDLE_NIL;
00131   }
00132   if (DDS::HANDLE_NIL == participant_permissions) {
00133     CommonUtilities::set_security_error(ex, -1, 0, "Invalid local permissions");
00134     return DDS::HANDLE_NIL;
00135   }
00136 
00137   if (!participant_security_attributes.is_rtps_protected) {
00138     return generate_handle();
00139   }
00140 
00141   CommonUtilities::set_security_error(ex, -1, 0, "Unsupported configuration");
00142   return DDS::HANDLE_NIL;
00143 }
00144 
00145 ParticipantCryptoHandle CryptoBuiltInImpl::register_matched_remote_participant(
00146   ParticipantCryptoHandle local_participant_crypto_handle,
00147   IdentityHandle remote_participant_identity,
00148   PermissionsHandle remote_participant_permissions,
00149   SharedSecretHandle* shared_secret,
00150   SecurityException& ex)
00151 {
00152   if (DDS::HANDLE_NIL == local_participant_crypto_handle) {
00153     CommonUtilities::set_security_error(ex, -1, 0, "Invalid local participant crypto handle");
00154     return DDS::HANDLE_NIL;
00155   }
00156   if (DDS::HANDLE_NIL == remote_participant_identity) {
00157     CommonUtilities::set_security_error(ex, -1, 0, "Invalid remote participant ID");
00158     return DDS::HANDLE_NIL;
00159   }
00160   if (DDS::HANDLE_NIL == remote_participant_permissions) {
00161     CommonUtilities::set_security_error(ex, -1, 0, "Invalid remote participant permissions");
00162     return DDS::HANDLE_NIL;
00163   }
00164   if (!shared_secret) {
00165     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Shared Secret data");
00166     return DDS::HANDLE_NIL;
00167   }
00168 
00169   return generate_handle();
00170 }
00171 
00172 namespace {
00173 
00174   bool operator==(const TAO::String_Manager& lhs, const char* rhs)
00175   {
00176     return 0 == std::strcmp(lhs, rhs);
00177   }
00178 
00179   bool operator==(const char* lhs, const TAO::String_Manager& rhs)
00180   {
00181     return 0 == std::strcmp(lhs, rhs);
00182   }
00183 
00184   bool is_builtin_volatile(const DDS::PropertySeq& props)
00185   {
00186     for (unsigned int i = 0; i < props.length(); ++i) {
00187       if (props[i].name == "dds.sec.builtin_endpoint_name") {
00188         return props[i].value == "BuiltinParticipantVolatileMessageSecureWriter"
00189           || props[i].value == "BuiltinParticipantVolatileMessageSecureReader";
00190       }
00191     }
00192     return false;
00193   }
00194 
00195   bool is_volatile_placeholder(const KeyMaterial_AES_GCM_GMAC& keymat)
00196   {
00197     static const CryptoTransformKind placeholder =
00198       {DCPS::VENDORID_OCI[0], DCPS::VENDORID_OCI[1], 0, 1};
00199     return 0 == std::memcmp(placeholder, keymat.transformation_kind,
00200                             sizeof placeholder);
00201   }
00202 
00203   KeyMaterial_AES_GCM_GMAC make_volatile_placeholder()
00204   {
00205     // not an actual key, just used to identify the local datawriter/reader
00206     // crypto handle for a Built-In Participant Volatile Msg endpoint
00207     const KeyMaterial_AES_GCM_GMAC k = {
00208       {DCPS::VENDORID_OCI[0], DCPS::VENDORID_OCI[1], 0, 1},
00209       KeyOctetSeq(), {0, 0, 0, 0}, KeyOctetSeq(), {0, 0, 0, 0}, KeyOctetSeq()
00210     };
00211     return k;
00212   }
00213 
00214   struct PrivateKey {
00215     EVP_PKEY* pkey_;
00216     explicit PrivateKey(const KeyOctetSeq& key)
00217       : pkey_(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, 0, key.get_buffer(),
00218                                    key.length())) {}
00219     explicit PrivateKey(const DDS::OctetSeq& key)
00220       : pkey_(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, 0, key.get_buffer(),
00221                                    key.length())) {}
00222     operator EVP_PKEY*() { return pkey_; }
00223     ~PrivateKey() { EVP_PKEY_free(pkey_); }
00224   };
00225 
00226   struct DigestContext {
00227     EVP_MD_CTX* ctx_;
00228     DigestContext() : ctx_(EVP_MD_CTX_new()) {}
00229     operator EVP_MD_CTX*() { return ctx_; }
00230     ~DigestContext() { EVP_MD_CTX_free(ctx_); }
00231   };
00232 
00233   void hkdf(KeyOctetSeq& result, const DDS::OctetSeq_var& prefix,
00234             const char (&cookie)[17], const DDS::OctetSeq_var& suffix,
00235             const DDS::OctetSeq_var& data)
00236   {
00237     char* cookie_buffer = const_cast<char*>(cookie); // OctetSeq has no const
00238     DDS::OctetSeq cookieSeq(16, 16,
00239                             reinterpret_cast<CORBA::Octet*>(cookie_buffer));
00240     std::vector<const DDS::OctetSeq*> input(3);
00241     input[0] = prefix.ptr();
00242     input[1] = &cookieSeq;
00243     input[2] = suffix.ptr();
00244     DDS::OctetSeq key;
00245     if (SSL::hash(input, key) != 0) {
00246       return;
00247     }
00248 
00249     PrivateKey pkey(key);
00250     DigestContext ctx;
00251     const EVP_MD* md = EVP_get_digestbyname("SHA256");
00252     if (EVP_DigestInit_ex(ctx, md, 0) != 1) {
00253       return;
00254     }
00255 
00256     if (EVP_DigestSignInit(ctx, 0, md, 0, pkey) != 1) {
00257       return;
00258     }
00259 
00260     if (EVP_DigestSignUpdate(ctx, data->get_buffer(), data->length()) != 1) {
00261       return;
00262     }
00263 
00264     size_t req = 0;
00265     if (EVP_DigestSignFinal(ctx, 0, &req) != 1) {
00266       return;
00267     }
00268 
00269     result.length(static_cast<unsigned int>(req));
00270     if (EVP_DigestSignFinal(ctx, result.get_buffer(), &req) != 1) {
00271       result.length(0);
00272     }
00273   }
00274 
00275   KeyMaterial_AES_GCM_GMAC
00276   make_volatile_key(const DDS::OctetSeq_var& challenge1,
00277                     const DDS::OctetSeq_var& challenge2,
00278                     const DDS::OctetSeq_var& sharedSec)
00279   {
00280     static const char KxSaltCookie[] = "keyexchange salt";
00281     static const char KxKeyCookie[] = "key exchange key";
00282     KeyMaterial_AES_GCM_GMAC k = {
00283       {0, 0, 0, CRYPTO_TRANSFORMATION_KIND_AES256_GCM},
00284       KeyOctetSeq(), {0, 0, 0, 0}, KeyOctetSeq(), {0, 0, 0, 0}, KeyOctetSeq()
00285     };
00286     hkdf(k.master_salt, challenge1, KxSaltCookie, challenge2, sharedSec);
00287     hkdf(k.master_sender_key, challenge2, KxKeyCookie, challenge1, sharedSec);
00288     return k;
00289   }
00290 }
00291 
00292 DatawriterCryptoHandle CryptoBuiltInImpl::register_local_datawriter(
00293   ParticipantCryptoHandle participant_crypto,
00294   const DDS::PropertySeq& properties,
00295   const EndpointSecurityAttributes& security_attributes,
00296   SecurityException& ex)
00297 {
00298   if (DDS::HANDLE_NIL == participant_crypto) {
00299     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Participant Crypto Handle");
00300     return DDS::HANDLE_NIL;
00301   }
00302 
00303   const NativeCryptoHandle h = generate_handle();
00304   const PluginEndpointSecurityAttributesMask plugin_attribs =
00305     security_attributes.plugin_endpoint_attributes;
00306   KeySeq keys;
00307 
00308   if (is_builtin_volatile(properties)) {
00309     push_back(keys, make_volatile_placeholder());
00310 
00311   } else {
00312     // See Table 70 "register_local_datawriter" for the use of the key sequence
00313     // (requirements for which key appears first, etc.)
00314     bool used_h = false;
00315     if (security_attributes.is_submessage_protected) {
00316       push_back(keys,
00317                 make_key(h, plugin_attribs & FLAG_IS_SUBMESSAGE_ENCRYPTED));
00318       used_h = true;
00319     }
00320     if (security_attributes.is_payload_protected) {
00321       const unsigned int key_id = used_h ? generate_handle() : h;
00322       push_back(keys,
00323                 make_key(key_id, plugin_attribs & FLAG_IS_PAYLOAD_ENCRYPTED));
00324     }
00325   }
00326 
00327   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00328   keys_[h] = keys;
00329   EntityInfo e(DATAWRITER_SUBMESSAGE, h);
00330   participant_to_entity_.insert(std::make_pair(participant_crypto, e));
00331   writer_options_[h] = security_attributes;
00332 
00333   return h;
00334 }
00335 
00336 DatareaderCryptoHandle CryptoBuiltInImpl::register_matched_remote_datareader(
00337   DatawriterCryptoHandle local_datawriter_crypto_handle,
00338   ParticipantCryptoHandle remote_participant_crypto,
00339   SharedSecretHandle* shared_secret,
00340   bool /*relay_only*/,
00341   SecurityException& ex)
00342 {
00343   if (DDS::HANDLE_NIL == local_datawriter_crypto_handle) {
00344     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Local DataWriter Crypto Handle");
00345     return DDS::HANDLE_NIL;
00346   }
00347   if (DDS::HANDLE_NIL == remote_participant_crypto) {
00348     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Remote Participant Crypto Handle");
00349     return DDS::HANDLE_NIL;
00350   }
00351   if (!shared_secret) {
00352     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Shared Secret Handle");
00353     return DDS::HANDLE_NIL;
00354   }
00355 
00356   const DatareaderCryptoHandle h = generate_handle();
00357   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00358   if (!keys_.count(local_datawriter_crypto_handle)) {
00359     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Local DataWriter Crypto Handle");
00360     return DDS::HANDLE_NIL;
00361   }
00362   const KeySeq& dw_keys = keys_[local_datawriter_crypto_handle];
00363 
00364   if (dw_keys.length() == 1 && is_volatile_placeholder(dw_keys[0])) {
00365     // Create a key from SharedSecret and track it as if Key Exchange happened
00366     KeySeq dr_keys(1);
00367     dr_keys.length(1);
00368     dr_keys[0] = make_volatile_key(shared_secret->challenge1(),
00369                                    shared_secret->challenge2(),
00370                                    shared_secret->sharedSecret());
00371     if (!dr_keys[0].master_salt.length()
00372         || !dr_keys[0].master_sender_key.length()) {
00373       CommonUtilities::set_security_error(ex, -1, 0, "Couldn't create key for "
00374                                           "volatile remote reader");
00375       return DDS::HANDLE_NIL;
00376     }
00377     keys_[h] = dr_keys;
00378   }
00379 
00380   EntityInfo e(DATAREADER_SUBMESSAGE, h);
00381   participant_to_entity_.insert(std::make_pair(remote_participant_crypto, e));
00382   return h;
00383 }
00384 
00385 DatareaderCryptoHandle CryptoBuiltInImpl::register_local_datareader(
00386   ParticipantCryptoHandle participant_crypto,
00387   const DDS::PropertySeq& properties,
00388   const EndpointSecurityAttributes& security_attributes,
00389   SecurityException& ex)
00390 {
00391   if (DDS::HANDLE_NIL == participant_crypto) {
00392     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Participant Crypto Handle");
00393     return DDS::HANDLE_NIL;
00394   }
00395 
00396   const NativeCryptoHandle h = generate_handle();
00397   const PluginEndpointSecurityAttributesMask plugin_attribs =
00398     security_attributes.plugin_endpoint_attributes;
00399   KeySeq keys;
00400 
00401   if (is_builtin_volatile(properties)) {
00402     push_back(keys, make_volatile_placeholder());
00403 
00404   } else {
00405     if (security_attributes.is_submessage_protected) {
00406       push_back(keys,
00407                 make_key(h, plugin_attribs & FLAG_IS_SUBMESSAGE_ENCRYPTED));
00408     }
00409   }
00410 
00411   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00412   keys_[h] = keys;
00413   EntityInfo e(DATAREADER_SUBMESSAGE, h);
00414   participant_to_entity_.insert(std::make_pair(participant_crypto, e));
00415   writer_options_[h] = security_attributes;
00416 
00417   return h;
00418 }
00419 
00420 DatawriterCryptoHandle CryptoBuiltInImpl::register_matched_remote_datawriter(
00421   DatareaderCryptoHandle local_datareader_crypto_handle,
00422   ParticipantCryptoHandle remote_participant_crypto,
00423   SharedSecretHandle* shared_secret,
00424   SecurityException& ex)
00425 {
00426   if (DDS::HANDLE_NIL == local_datareader_crypto_handle) {
00427     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Local DataReader Crypto Handle");
00428     return DDS::HANDLE_NIL;
00429   }
00430   if (DDS::HANDLE_NIL == remote_participant_crypto) {
00431     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Remote Participant Crypto Handle");
00432     return DDS::HANDLE_NIL;
00433   }
00434   if (!shared_secret) {
00435     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Shared Secret Handle");
00436     return DDS::HANDLE_NIL;
00437   }
00438 
00439   const DatareaderCryptoHandle h = generate_handle();
00440   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00441   if (!keys_.count(local_datareader_crypto_handle)) {
00442     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Local DataReader Crypto Handle");
00443     return DDS::HANDLE_NIL;
00444   }
00445   const KeySeq& dr_keys = keys_[local_datareader_crypto_handle];
00446 
00447   if (dr_keys.length() == 1 && is_volatile_placeholder(dr_keys[0])) {
00448     // Create a key from SharedSecret and track it as if Key Exchange happened
00449     KeySeq dw_keys(1);
00450     dw_keys.length(1);
00451     dw_keys[0] = make_volatile_key(shared_secret->challenge1(),
00452                                    shared_secret->challenge2(),
00453                                    shared_secret->sharedSecret());
00454     if (!dw_keys[0].master_salt.length()
00455         || !dw_keys[0].master_sender_key.length()) {
00456       CommonUtilities::set_security_error(ex, -1, 0, "Couldn't create key for "
00457                                           "volatile remote writer");
00458       return DDS::HANDLE_NIL;
00459     }
00460     keys_[h] = dw_keys;
00461   }
00462 
00463   EntityInfo e(DATAWRITER_SUBMESSAGE, h);
00464   participant_to_entity_.insert(std::make_pair(remote_participant_crypto, e));
00465   writer_options_[h] = writer_options_[local_datareader_crypto_handle];
00466   return h;
00467 }
00468 
00469 bool CryptoBuiltInImpl::unregister_participant(ParticipantCryptoHandle handle, SecurityException& ex)
00470 {
00471   if (DDS::HANDLE_NIL == handle) {
00472     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Crypto Handle");
00473     return false;
00474   }
00475   return true;
00476 }
00477 
00478 void CryptoBuiltInImpl::clear_endpoint_data(NativeCryptoHandle handle)
00479 {
00480   keys_.erase(handle);
00481 
00482   typedef std::multimap<ParticipantCryptoHandle, EntityInfo>::iterator iter_t;
00483   for (iter_t it = participant_to_entity_.begin(); it != participant_to_entity_.end();) {
00484     if (it->second.handle_ == handle) {
00485       participant_to_entity_.erase(it++);
00486     } else {
00487       ++it;
00488     }
00489   }
00490 
00491   for (SessionTable_t::iterator st_iter = sessions_.lower_bound(std::make_pair(handle, 0));
00492        st_iter != sessions_.end() && st_iter->first.first == handle;
00493        sessions_.erase(st_iter++)) {
00494   }
00495 }
00496 
00497 bool CryptoBuiltInImpl::unregister_datawriter(DatawriterCryptoHandle handle, SecurityException& ex)
00498 {
00499   if (DDS::HANDLE_NIL == handle) {
00500     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Crypto Handle");
00501     return false;
00502   }
00503 
00504   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00505   writer_options_.erase(handle);
00506   clear_endpoint_data(handle);
00507   return true;
00508 }
00509 
00510 bool CryptoBuiltInImpl::unregister_datareader(DatareaderCryptoHandle handle, SecurityException& ex)
00511 {
00512   if (DDS::HANDLE_NIL == handle) {
00513     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Crypto Handle");
00514     return false;
00515   }
00516 
00517   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00518   clear_endpoint_data(handle);
00519   return true;
00520 }
00521 
00522 
00523 // Key Exchange
00524 
00525 namespace {
00526   const char Crypto_Token_Class_Id[] = "DDS:Crypto:AES_GCM_GMAC";
00527   const char Token_KeyMat_Name[] = "dds.cryp.keymat";
00528 
00529   const char* to_mb(const unsigned char* buffer)
00530   {
00531     return reinterpret_cast<const char*>(buffer);
00532   }
00533 
00534   ParticipantCryptoTokenSeq
00535   keys_to_tokens(const KeyMaterial_AES_GCM_GMAC_Seq& keys)
00536   {
00537     ParticipantCryptoTokenSeq tokens;
00538     for (unsigned int i = 0; i < keys.length(); ++i) {
00539       CryptoToken t;
00540       t.class_id = Crypto_Token_Class_Id;
00541       t.binary_properties.length(1);
00542       DDS::BinaryProperty_t& p = t.binary_properties[0];
00543       p.name = Token_KeyMat_Name;
00544       p.propagate = true;
00545       size_t size = 0, padding = 0;
00546       DCPS::gen_find_size(keys[i], size, padding);
00547       p.value.length(static_cast<unsigned int>(size + padding));
00548       ACE_Message_Block mb(to_mb(p.value.get_buffer()), size + padding);
00549       Serializer ser(&mb, Serializer::SWAP_BE, Serializer::ALIGN_CDR);
00550       if (ser << keys[i]) {
00551         push_back(tokens, t);
00552       }
00553     }
00554     return tokens;
00555   }
00556 
00557   KeyMaterial_AES_GCM_GMAC_Seq
00558   tokens_to_keys(const ParticipantCryptoTokenSeq& tokens)
00559   {
00560     KeyMaterial_AES_GCM_GMAC_Seq keys;
00561     for (unsigned int i = 0; i < tokens.length(); ++i) {
00562       const CryptoToken& t = tokens[i];
00563       if (Crypto_Token_Class_Id == t.class_id) {
00564         for (unsigned int j = 0; j < t.binary_properties.length(); ++j) {
00565           const DDS::BinaryProperty_t& p = t.binary_properties[j];
00566           if (Token_KeyMat_Name == p.name) {
00567             ACE_Message_Block mb(to_mb(p.value.get_buffer()), p.value.length());
00568             mb.wr_ptr(p.value.length());
00569             Serializer ser(&mb, Serializer::SWAP_BE, Serializer::ALIGN_CDR);
00570             KeyMaterial_AES_GCM_GMAC key;
00571             if (ser >> key) {
00572               push_back(keys, key);
00573             }
00574             break;
00575           }
00576         }
00577       }
00578     }
00579     return keys;
00580   }
00581 }
00582 
00583 bool CryptoBuiltInImpl::create_local_participant_crypto_tokens(
00584   ParticipantCryptoTokenSeq& local_participant_crypto_tokens,
00585   ParticipantCryptoHandle local_participant_crypto,
00586   ParticipantCryptoHandle remote_participant_crypto,
00587   SecurityException& ex)
00588 {
00589   if (DDS::HANDLE_NIL == local_participant_crypto) {
00590     CommonUtilities::set_security_error(ex, -1, 0,
00591                                         "Invalid local participant handle");
00592     return false;
00593   }
00594   if (DDS::HANDLE_NIL == remote_participant_crypto) {
00595     CommonUtilities::set_security_error(ex, -1, 0,
00596                                         "Invalid remote participant handle");
00597     return false;
00598   }
00599 
00600   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00601   if (keys_.count(local_participant_crypto)) {
00602     local_participant_crypto_tokens =
00603       keys_to_tokens(keys_[local_participant_crypto]);
00604   } else {
00605     // There may not be any keys_ for this participant (depends on config)
00606     local_participant_crypto_tokens.length(0);
00607   }
00608 
00609   return true;
00610 }
00611 
00612 bool CryptoBuiltInImpl::set_remote_participant_crypto_tokens(
00613   ParticipantCryptoHandle local_participant_crypto,
00614   ParticipantCryptoHandle remote_participant_crypto,
00615   const ParticipantCryptoTokenSeq& remote_participant_tokens,
00616   SecurityException& ex)
00617 {
00618   if (DDS::HANDLE_NIL == local_participant_crypto) {
00619     CommonUtilities::set_security_error(ex, -1, 0,
00620                                         "Invalid local participant handle");
00621     return false;
00622   }
00623   if (DDS::HANDLE_NIL == remote_participant_crypto) {
00624     CommonUtilities::set_security_error(ex, -1, 0,
00625                                         "Invalid remote participant handle");
00626     return false;
00627   }
00628 
00629   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00630   keys_[remote_participant_crypto] = tokens_to_keys(remote_participant_tokens);
00631   return true;
00632 }
00633 
00634 bool CryptoBuiltInImpl::create_local_datawriter_crypto_tokens(
00635   DatawriterCryptoTokenSeq& local_datawriter_crypto_tokens,
00636   DatawriterCryptoHandle local_datawriter_crypto,
00637   DatareaderCryptoHandle remote_datareader_crypto,
00638   SecurityException& ex)
00639 {
00640   if (DDS::HANDLE_NIL == local_datawriter_crypto) {
00641     CommonUtilities::set_security_error(ex, -1, 0, "Invalid local writer handle");
00642     return false;
00643   }
00644   if (DDS::HANDLE_NIL == remote_datareader_crypto) {
00645     CommonUtilities::set_security_error(ex, -1, 0, "Invalid remote reader handle");
00646     return false;
00647   }
00648 
00649   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00650   if (keys_.count(local_datawriter_crypto)) {
00651     local_datawriter_crypto_tokens =
00652       keys_to_tokens(keys_[local_datawriter_crypto]);
00653   } else {
00654     local_datawriter_crypto_tokens.length(0);
00655   }
00656 
00657   return true;
00658 }
00659 
00660 bool CryptoBuiltInImpl::set_remote_datawriter_crypto_tokens(
00661   DatareaderCryptoHandle local_datareader_crypto,
00662   DatawriterCryptoHandle remote_datawriter_crypto,
00663   const DatawriterCryptoTokenSeq& remote_datawriter_tokens,
00664   SecurityException& ex)
00665 {
00666   if (DDS::HANDLE_NIL == local_datareader_crypto) {
00667     CommonUtilities::set_security_error(ex, -1, 0,
00668                                         "Invalid local datareader handle");
00669     return false;
00670   }
00671   if (DDS::HANDLE_NIL == remote_datawriter_crypto) {
00672     CommonUtilities::set_security_error(ex, -1, 0,
00673                                         "Invalid remote datawriter handle");
00674     return false;
00675   }
00676 
00677   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00678   keys_[remote_datawriter_crypto] = tokens_to_keys(remote_datawriter_tokens);
00679   return true;
00680 }
00681 
00682 bool CryptoBuiltInImpl::create_local_datareader_crypto_tokens(
00683   DatareaderCryptoTokenSeq& local_datareader_crypto_tokens,
00684   DatareaderCryptoHandle local_datareader_crypto,
00685   DatawriterCryptoHandle remote_datawriter_crypto,
00686   SecurityException& ex)
00687 {
00688   if (DDS::HANDLE_NIL == local_datareader_crypto) {
00689     CommonUtilities::set_security_error(ex, -1, 0, "Invalid local reader handle");
00690     return false;
00691   }
00692   if (DDS::HANDLE_NIL == remote_datawriter_crypto) {
00693     CommonUtilities::set_security_error(ex, -1, 0, "Invalid remote writer handle");
00694     return false;
00695   }
00696 
00697   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00698   if (keys_.count(local_datareader_crypto)) {
00699     local_datareader_crypto_tokens =
00700       keys_to_tokens(keys_[local_datareader_crypto]);
00701   } else {
00702     local_datareader_crypto_tokens.length(0);
00703   }
00704 
00705   return true;
00706 }
00707 
00708 bool CryptoBuiltInImpl::set_remote_datareader_crypto_tokens(
00709   DatawriterCryptoHandle local_datawriter_crypto,
00710   DatareaderCryptoHandle remote_datareader_crypto,
00711   const DatareaderCryptoTokenSeq& remote_datareader_tokens,
00712   SecurityException& ex)
00713 {
00714   if (DDS::HANDLE_NIL == local_datawriter_crypto) {
00715     CommonUtilities::set_security_error(ex, -1, 0,
00716                                         "Invalid local datawriter handle");
00717     return false;
00718   }
00719   if (DDS::HANDLE_NIL == remote_datareader_crypto) {
00720     CommonUtilities::set_security_error(ex, -1, 0,
00721                                         "Invalid remote datareader handle");
00722     return false;
00723   }
00724 
00725   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00726   keys_[remote_datareader_crypto] = tokens_to_keys(remote_datareader_tokens);
00727   return true;
00728 }
00729 
00730 bool CryptoBuiltInImpl::return_crypto_tokens(const CryptoTokenSeq&, SecurityException&)
00731 {
00732   return true;
00733 }
00734 
00735 
00736 // Transform
00737 
00738 namespace {
00739   bool encrypts(const KeyMaterial_AES_GCM_GMAC& k)
00740   {
00741     const CryptoTransformKind& kind = k.transformation_kind;
00742     return kind[0] == 0 && kind[1] == 0 && kind[2] == 0
00743       && (kind[TransformKindIndex] == CRYPTO_TRANSFORMATION_KIND_AES128_GCM ||
00744           kind[TransformKindIndex] == CRYPTO_TRANSFORMATION_KIND_AES256_GCM);
00745   }
00746 
00747   bool authenticates(const KeyMaterial_AES_GCM_GMAC& k)
00748   {
00749     const CryptoTransformKind& kind = k.transformation_kind;
00750     return kind[0] == 0 && kind[1] == 0 && kind[2] == 0
00751       && (kind[TransformKindIndex] == CRYPTO_TRANSFORMATION_KIND_AES128_GMAC ||
00752           kind[TransformKindIndex] == CRYPTO_TRANSFORMATION_KIND_AES256_GMAC);
00753   }
00754 
00755   struct CipherContext {
00756     EVP_CIPHER_CTX* ctx_;
00757     CipherContext() : ctx_(EVP_CIPHER_CTX_new()) {}
00758     operator EVP_CIPHER_CTX*() { return ctx_; }
00759     ~CipherContext() { EVP_CIPHER_CTX_free(ctx_); }
00760   };
00761 
00762   bool inc32(unsigned char* a)
00763   {
00764     for (int i = 0; i < 4; ++i) {
00765       if (a[i] != 0xff) {
00766         ++a[i];
00767         return false;
00768       }
00769     }
00770     std::fill(a, a + 4, 0);
00771     return true;
00772   }
00773 
00774   const size_t CRYPTO_CONTENT_ADDED_LENGTH = 4;
00775   const size_t CRYPTO_HEADER_LENGTH = 20;
00776 }
00777 
00778 bool CryptoBuiltInImpl::encode_serialized_payload(
00779   DDS::OctetSeq& encoded_buffer,
00780   DDS::OctetSeq& /*extra_inline_qos*/,
00781   const DDS::OctetSeq& plain_buffer,
00782   DatawriterCryptoHandle sending_datawriter_crypto,
00783   SecurityException& ex)
00784 {
00785   if (DDS::HANDLE_NIL == sending_datawriter_crypto) {
00786     CommonUtilities::set_security_error(ex, -1, 0, "Invalid datawriter handle");
00787     return false;
00788   }
00789 
00790   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00791   if (!keys_.count(sending_datawriter_crypto)
00792       || !writer_options_[sending_datawriter_crypto].payload_) {
00793     encoded_buffer = plain_buffer;
00794     return true;
00795   }
00796 
00797   const KeySeq& keyseq = keys_[sending_datawriter_crypto];
00798   if (!keyseq.length()) {
00799     encoded_buffer = plain_buffer;
00800     return true;
00801   }
00802 
00803   bool ok;
00804   CryptoHeader header;
00805   CryptoFooter footer;
00806   DDS::OctetSeq out;
00807   const DDS::OctetSeq* pOut = &plain_buffer;
00808   // see register_local_datawriter for the assignment of key indexes in the seq
00809   const unsigned int key_idx = keyseq.length() >= 2 ? 1 : 0;
00810   const KeyId_t sKey = std::make_pair(sending_datawriter_crypto, key_idx);
00811 
00812   if (encrypts(keyseq[key_idx])) {
00813     ok = encrypt(keyseq[key_idx], sessions_[sKey], plain_buffer,
00814                  header, footer, out, ex);
00815     pOut = &out;
00816   } else if (authenticates(keyseq[key_idx])) {
00817     ok = authtag(keyseq[key_idx], sessions_[sKey], plain_buffer,
00818                  header, footer, ex);
00819   } else {
00820     ok = false;
00821     CommonUtilities::set_security_error(ex, -1, 0,
00822                                         "Key transform kind unrecognized");
00823   }
00824 
00825   if (!ok) {
00826     return false;
00827   }
00828 
00829   size_t size = 0, padding = 0;
00830   using DCPS::gen_find_size;
00831   gen_find_size(header, size, padding);
00832 
00833   if (pOut != &plain_buffer) {
00834     size += CRYPTO_CONTENT_ADDED_LENGTH;
00835   }
00836 
00837   size += pOut->length();
00838   gen_find_size(footer, size, padding);
00839 
00840   encoded_buffer.length(size + padding);
00841   ACE_Message_Block mb(to_mb(encoded_buffer.get_buffer()), size + padding);
00842   Serializer ser(&mb, Serializer::SWAP_BE, Serializer::ALIGN_CDR);
00843   ser << header;
00844 
00845   if (pOut != &plain_buffer) {
00846     ser << pOut->length();
00847   }
00848   ser.write_octet_array(pOut->get_buffer(), pOut->length());
00849 
00850   ser << footer;
00851   return true;
00852 }
00853 
00854 void CryptoBuiltInImpl::Session::create_key(const KeyMaterial& master)
00855 {
00856   RAND_bytes(id_, sizeof id_);
00857   RAND_bytes(iv_suffix_, sizeof iv_suffix_);
00858   derive_key(master);
00859   counter_ = 0;
00860 }
00861 
00862 void CryptoBuiltInImpl::Session::next_id(const KeyMaterial& master)
00863 {
00864   inc32(id_);
00865   RAND_bytes(iv_suffix_, sizeof iv_suffix_);
00866   key_.length(0);
00867   derive_key(master);
00868   counter_ = 0;
00869 }
00870 
00871 void CryptoBuiltInImpl::Session::inc_iv()
00872 {
00873   if (inc32(iv_suffix_)) {
00874     inc32(iv_suffix_ + 4);
00875   }
00876 }
00877 
00878 void CryptoBuiltInImpl::encauth_setup(const KeyMaterial& master, Session& sess,
00879                                       const DDS::OctetSeq& plain,
00880                                       CryptoHeader& header)
00881 {
00882   const unsigned int blocks =
00883     (plain.length() + BLOCK_LEN_BYTES - 1) / BLOCK_LEN_BYTES;
00884 
00885   if (!sess.key_.length()) {
00886     sess.create_key(master);
00887 
00888   } else if (sess.counter_ + blocks > MAX_BLOCKS_PER_SESSION) {
00889     sess.next_id(master);
00890 
00891   } else {
00892     sess.inc_iv();
00893     sess.counter_ += blocks;
00894   }
00895 
00896   std::memcpy(&header.transform_identifier.transformation_kind,
00897               &master.transformation_kind, sizeof master.transformation_kind);
00898   std::memcpy(&header.transform_identifier.transformation_key_id,
00899               &master.sender_key_id, sizeof master.sender_key_id);
00900   std::memcpy(&header.session_id, &sess.id_, sizeof sess.id_);
00901   std::memcpy(&header.initialization_vector_suffix, &sess.iv_suffix_,
00902               sizeof sess.iv_suffix_);
00903 }
00904 
00905 bool CryptoBuiltInImpl::encrypt(const KeyMaterial& master, Session& sess,
00906                                 const DDS::OctetSeq& plain,
00907                                 CryptoHeader& header, CryptoFooter& footer,
00908                                 DDS::OctetSeq& out, SecurityException& ex)
00909 {
00910   encauth_setup(master, sess, plain, header);
00911   static const int IV_LEN = 12, IV_SUFFIX_IDX = 4;
00912   unsigned char iv[IV_LEN];
00913   std::memcpy(iv, &sess.id_, sizeof sess.id_);
00914   std::memcpy(iv + IV_SUFFIX_IDX, &sess.iv_suffix_, sizeof sess.iv_suffix_);
00915 
00916   CipherContext ctx;
00917   const unsigned char* key = sess.key_.get_buffer();
00918   if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), 0, key, iv) != 1) {
00919     CommonUtilities::set_security_error(ex, -1, 0, "EVP_EncryptInit_ex");
00920     return false;
00921   }
00922 
00923   int len;
00924   out.length(plain.length() + BLOCK_LEN_BYTES - 1);
00925   if (EVP_EncryptUpdate(ctx, out.get_buffer(), &len,
00926                         plain.get_buffer(), plain.length()) != 1) {
00927     CommonUtilities::set_security_error(ex, -1, 0, "EVP_EncryptUpdate");
00928     return false;
00929   }
00930 
00931   int padLen;
00932   if (EVP_EncryptFinal_ex(ctx, out.get_buffer() + len, &padLen) != 1) {
00933     CommonUtilities::set_security_error(ex, -1, 0, "EVP_EncryptFinal_ex");
00934     return false;
00935   }
00936 
00937   out.length(len + padLen);
00938 
00939   if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, sizeof footer.common_mac,
00940                           &footer.common_mac) != 1) {
00941     CommonUtilities::set_security_error(ex, -1, 0, "EVP_CIPHER_CTX_ctrl");
00942     return false;
00943   }
00944 
00945   return true;
00946 }
00947 
00948 bool CryptoBuiltInImpl::authtag(const KeyMaterial& master, Session& sess,
00949                                 const DDS::OctetSeq& plain,
00950                                 CryptoHeader& header,
00951                                 CryptoFooter& footer,
00952                                 SecurityException& ex)
00953 {
00954   encauth_setup(master, sess, plain, header);
00955   static const int IV_LEN = 12, IV_SUFFIX_IDX = 4;
00956   unsigned char iv[IV_LEN];
00957   std::memcpy(iv, &sess.id_, sizeof sess.id_);
00958   std::memcpy(iv + IV_SUFFIX_IDX, &sess.iv_suffix_, sizeof sess.iv_suffix_);
00959 
00960   CipherContext ctx;
00961   const unsigned char* key = sess.key_.get_buffer();
00962   if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), 0, key, iv) != 1) {
00963     CommonUtilities::set_security_error(ex, -1, 0, "EVP_EncryptInit_ex");
00964     return false;
00965   }
00966 
00967   int n;
00968   if (EVP_EncryptUpdate(ctx, 0, &n, plain.get_buffer(), plain.length()) != 1) {
00969     CommonUtilities::set_security_error(ex, -1, 0, "EVP_EncryptUpdate");
00970     return false;
00971   }
00972 
00973   if (EVP_EncryptFinal_ex(ctx, 0, &n) != 1) {
00974     CommonUtilities::set_security_error(ex, -1, 0, "EVP_EncryptFinal_ex");
00975     return false;
00976   }
00977 
00978   if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, sizeof footer.common_mac,
00979                           &footer.common_mac) != 1) {
00980     CommonUtilities::set_security_error(ex, -1, 0, "EVP_CIPHER_CTX_ctrl");
00981     return false;
00982   }
00983 
00984   return true;
00985 }
00986 
00987 bool CryptoBuiltInImpl::encode_submessage(
00988   DDS::OctetSeq& encoded_rtps_submessage,
00989   const DDS::OctetSeq& plain_rtps_submessage,
00990   NativeCryptoHandle sender_handle,
00991   SecurityException& ex)
00992 {
00993   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
00994   if (!keys_.count(sender_handle)) {
00995     encoded_rtps_submessage = plain_rtps_submessage;
00996     return true;
00997   }
00998 
00999   const KeySeq& keyseq = keys_[sender_handle];
01000   if (!keyseq.length()) {
01001     encoded_rtps_submessage = plain_rtps_submessage;
01002     return true;
01003   }
01004 
01005   bool ok;
01006   CryptoHeader header;
01007   CryptoFooter footer;
01008   DDS::OctetSeq out;
01009   const DDS::OctetSeq* pOut = &plain_rtps_submessage;
01010   static const unsigned int SUBMSG_KEY_IDX = 0;
01011   const KeyId_t sKey = std::make_pair(sender_handle, SUBMSG_KEY_IDX);
01012   bool authOnly = false;
01013 
01014   if (encrypts(keyseq[SUBMSG_KEY_IDX])) {
01015     ok = encrypt(keyseq[SUBMSG_KEY_IDX], sessions_[sKey], plain_rtps_submessage,
01016                  header, footer, out, ex);
01017     pOut = &out;
01018   } else if (authenticates(keyseq[SUBMSG_KEY_IDX])) {
01019     // the original submessage may have octetsToNextHeader = 0 which isn't
01020     // legal when appending SEC_POSTFIX, patch in the actual submsg length
01021     ACE_Message_Block mb_in(to_mb(pOut->get_buffer()), pOut->length());
01022     mb_in.wr_ptr(pOut->length());
01023     Serializer ser_in(&mb_in);
01024     RTPS::SubmessageHeader smHdr_in;
01025     ser_in >> ACE_InputCDR::to_octet(smHdr_in.submessageId);
01026     ser_in >> ACE_InputCDR::to_octet(smHdr_in.flags);
01027     ser_in.swap_bytes(ACE_CDR_BYTE_ORDER != (smHdr_in.flags & 1));
01028     ser_in >> smHdr_in.submessageLength;
01029     if (!smHdr_in.submessageLength) {
01030       out = *pOut;
01031       unsigned int len = pOut->length() - 4;
01032       out[2 + !(smHdr_in.flags & 1)] = len & 0xff;
01033       out[2 + (smHdr_in.flags & 1)] = (len >> 8) & 0xff;
01034       pOut = &out;
01035     }
01036     ok = authtag(keyseq[SUBMSG_KEY_IDX], sessions_[sKey], *pOut,
01037                  header, footer, ex);
01038     authOnly = true;
01039   } else {
01040     ok = false;
01041     CommonUtilities::set_security_error(ex, -1, 0,
01042                                         "Key transform kind unrecognized");
01043   }
01044 
01045   if (!ok) {
01046     return false;
01047   }
01048 
01049   size_t size = 0, padding = 0;
01050   size += 4; // prefix submessage header
01051   using DCPS::gen_find_size;
01052   gen_find_size(header, size, padding);
01053   const ACE_UINT16 hdrLen = static_cast<ACE_UINT16>(size + padding - 4);
01054 
01055   if (!authOnly) {
01056     size += 8; // body submessage header + seq len
01057   }
01058 
01059   size += pOut->length(); // submessage inside wrapper
01060   if ((size + padding) % 4) {
01061     padding += 4 - ((size + padding) % 4);
01062   }
01063 
01064   size += 4; // postfix submessage header
01065   size_t preFooter = size + padding;
01066   gen_find_size(footer, size, padding);
01067 
01068   encoded_rtps_submessage.length(size + padding);
01069   ACE_Message_Block mb(to_mb(encoded_rtps_submessage.get_buffer()),
01070                        size + padding);
01071   Serializer ser(&mb, Serializer::SWAP_BE, Serializer::ALIGN_CDR);
01072   RTPS::SubmessageHeader smHdr = {RTPS::SEC_PREFIX, 0, hdrLen};
01073   ser << smHdr;
01074   ser << header;
01075 
01076   if (!authOnly) {
01077     smHdr.submessageId = RTPS::SEC_BODY;
01078     smHdr.submessageLength = static_cast<ACE_UINT16>(4 + pOut->length());
01079     if (pOut->length() % 4) {
01080       smHdr.submessageLength += 4 - pOut->length() % 4;
01081     }
01082     ser << smHdr;
01083     ser << pOut->length();
01084   }
01085 
01086   ser.write_octet_array(pOut->get_buffer(), pOut->length());
01087   ser.align_w(4);
01088 
01089   smHdr.submessageId = RTPS::SEC_POSTFIX;
01090   smHdr.submessageLength = static_cast<ACE_UINT16>(size + padding - preFooter);
01091   ser << smHdr;
01092   ser << footer;
01093 
01094   return true;
01095 }
01096 
01097 bool CryptoBuiltInImpl::encode_datawriter_submessage(
01098   DDS::OctetSeq& encoded_rtps_submessage,
01099   const DDS::OctetSeq& plain_rtps_submessage,
01100   DatawriterCryptoHandle sending_datawriter_crypto,
01101   const DatareaderCryptoHandleSeq& receiving_datareader_crypto_list,
01102   CORBA::Long& receiving_datareader_crypto_list_index,
01103   SecurityException& ex)
01104 {
01105   if (DDS::HANDLE_NIL == sending_datawriter_crypto) {
01106     CommonUtilities::set_security_error(ex, -1, 0, "Invalid DataWriter handle");
01107     return false;
01108   }
01109 
01110   if (receiving_datareader_crypto_list_index < 0) {
01111     CommonUtilities::set_security_error(ex, -1, 0, "Negative list index");
01112     return false;
01113   }
01114 
01115   const int len = static_cast<int>(receiving_datareader_crypto_list.length());
01116   // NOTE: as an extension to the spec, this plugin allows an empty list in the
01117   // case where the writer is sending to all associated readers.
01118   if (len && receiving_datareader_crypto_list_index >= len) {
01119     CommonUtilities::set_security_error(ex, -1, 0, "List index too large");
01120     return false;
01121   }
01122 
01123   for (unsigned int i = 0; i < receiving_datareader_crypto_list.length(); ++i) {
01124     if (receiving_datareader_crypto_list[i] == DDS::HANDLE_NIL) {
01125       CommonUtilities::set_security_error(ex, -1, 0,
01126                                           "Invalid DataReader handle in list");
01127       return false;
01128     }
01129   }
01130 
01131   NativeCryptoHandle encode_handle = sending_datawriter_crypto;
01132   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
01133   if (!writer_options_[encode_handle].submessage_) {
01134     encoded_rtps_submessage = plain_rtps_submessage;
01135     receiving_datareader_crypto_list_index = len;
01136     return true;
01137   }
01138 
01139   if (receiving_datareader_crypto_list.length() == 1) {
01140     if (keys_.count(encode_handle)) {
01141       const KeySeq& dw_keys = keys_[encode_handle];
01142       if (dw_keys.length() == 1 && is_volatile_placeholder(dw_keys[0])) {
01143         encode_handle = receiving_datareader_crypto_list[0];
01144       }
01145     }
01146   }
01147 
01148   guard.release();
01149 
01150   const bool ok = encode_submessage(encoded_rtps_submessage,
01151                                     plain_rtps_submessage, encode_handle, ex);
01152   if (ok) {
01153     receiving_datareader_crypto_list_index = len;
01154   }
01155   return ok;
01156 }
01157 
01158 bool CryptoBuiltInImpl::encode_datareader_submessage(
01159   DDS::OctetSeq& encoded_rtps_submessage,
01160   const DDS::OctetSeq& plain_rtps_submessage,
01161   DatareaderCryptoHandle sending_datareader_crypto,
01162   const DatawriterCryptoHandleSeq& receiving_datawriter_crypto_list,
01163   SecurityException& ex)
01164 {
01165   if (DDS::HANDLE_NIL == sending_datareader_crypto) {
01166     CommonUtilities::set_security_error(ex, -1, 0, "Invalid DataReader handle");
01167     return false;
01168   }
01169 
01170   for (unsigned int i = 0; i < receiving_datawriter_crypto_list.length(); ++i) {
01171     if (receiving_datawriter_crypto_list[i] == DDS::HANDLE_NIL) {
01172       CommonUtilities::set_security_error(ex, -1, 0,
01173                                           "Invalid DataWriter handle in list");
01174       return false;
01175     }
01176   }
01177 
01178   NativeCryptoHandle encode_handle = sending_datareader_crypto;
01179   if (receiving_datawriter_crypto_list.length() == 1) {
01180     ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
01181     if (keys_.count(encode_handle)) {
01182       const KeySeq& dr_keys = keys_[encode_handle];
01183       if (dr_keys.length() == 1 && is_volatile_placeholder(dr_keys[0])) {
01184         encode_handle = receiving_datawriter_crypto_list[0];
01185       }
01186     }
01187   }
01188 
01189   return encode_submessage(encoded_rtps_submessage, plain_rtps_submessage,
01190                            encode_handle, ex);
01191 }
01192 
01193 bool CryptoBuiltInImpl::encode_rtps_message(
01194   DDS::OctetSeq& encoded_rtps_message,
01195   const DDS::OctetSeq& plain_rtps_message,
01196   ParticipantCryptoHandle sending_participant_crypto,
01197   const ParticipantCryptoHandleSeq& receiving_participant_crypto_list,
01198   CORBA::Long& receiving_participant_crypto_list_index,
01199   SecurityException& ex)
01200 {
01201   // Perform sanity checking on input data
01202   if (DDS::HANDLE_NIL == sending_participant_crypto) {
01203     CommonUtilities::set_security_error(ex, -1, 0, "Invalid DataReader handle");
01204     return false;
01205   }
01206   if (0 == receiving_participant_crypto_list.length()) {
01207     CommonUtilities::set_security_error(ex, -1, 0, "No Datawriters specified");
01208     return false;
01209   }
01210 
01211   ParticipantCryptoHandle dest_handle = DDS::HANDLE_NIL;
01212   if (receiving_participant_crypto_list_index >= 0) {
01213     // Need to make this unsigned to get prevent warnings when comparing to length()
01214     CORBA::ULong index = static_cast<CORBA::ULong>(receiving_participant_crypto_list_index);
01215     if (index < receiving_participant_crypto_list.length()) {
01216       dest_handle = receiving_participant_crypto_list[receiving_participant_crypto_list_index];
01217     }
01218   }
01219 
01220   if (DDS::HANDLE_NIL == dest_handle) {
01221     CommonUtilities::set_security_error(ex, -1, 0, "Invalid receiver handle");
01222     return false;
01223   }
01224 
01225   // Simple implementation wraps the plain_buffer back into the output
01226   // and adds no extra_inline_qos
01227   DDS::OctetSeq transformed_buffer(plain_rtps_message);
01228   encoded_rtps_message.swap(transformed_buffer);
01229 
01230   // Advance the counter to indicate this reader has been handled
01231   ++receiving_participant_crypto_list_index;
01232 
01233   return true;
01234 }
01235 
01236 namespace {
01237   bool matches(const KeyMaterial_AES_GCM_GMAC& k, const CryptoHeader& h)
01238   {
01239     return 0 == std::memcmp(k.transformation_kind,
01240                             h.transform_identifier.transformation_kind,
01241                             sizeof(CryptoTransformKind))
01242       && 0 == std::memcmp(k.sender_key_id,
01243                           h.transform_identifier.transformation_key_id,
01244                           sizeof(CryptoTransformKeyId));
01245   }
01246 }
01247 
01248 bool CryptoBuiltInImpl::decode_rtps_message(
01249   DDS::OctetSeq& plain_buffer,
01250   const DDS::OctetSeq& encoded_buffer,
01251   ParticipantCryptoHandle receiving_participant_crypto,
01252   ParticipantCryptoHandle sending_participant_crypto,
01253   SecurityException& ex)
01254 {
01255   // Perform sanity checking on input data
01256   if (DDS::HANDLE_NIL == receiving_participant_crypto) {
01257     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Receiving Participant handle");
01258     return false;
01259   }
01260   if (DDS::HANDLE_NIL == sending_participant_crypto) {
01261     CommonUtilities::set_security_error(ex, -1, 0, "No Sending Participant handle");
01262     return false;
01263   }
01264 
01265   // For the stub, just supply the input as the output
01266   DDS::OctetSeq transformed_buffer(encoded_buffer);
01267   plain_buffer.swap(transformed_buffer);
01268 
01269   return true;
01270 }
01271 
01272 bool CryptoBuiltInImpl::preprocess_secure_submsg(
01273   DatawriterCryptoHandle& datawriter_crypto,
01274   DatareaderCryptoHandle& datareader_crypto,
01275   SecureSubmessageCategory_t& secure_submessage_category,
01276   const DDS::OctetSeq& encoded_rtps_submessage,
01277   ParticipantCryptoHandle receiving_participant_crypto,
01278   ParticipantCryptoHandle sending_participant_crypto,
01279   SecurityException& ex)
01280 {
01281   if (DDS::HANDLE_NIL == receiving_participant_crypto) {
01282     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Receiving Participant");
01283     return false;
01284   }
01285   if (DDS::HANDLE_NIL == sending_participant_crypto) {
01286     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Sending Participant");
01287     return false;
01288   }
01289 
01290   ACE_Message_Block mb_in(to_mb(encoded_rtps_submessage.get_buffer()),
01291                           encoded_rtps_submessage.length());
01292   mb_in.wr_ptr(encoded_rtps_submessage.length());
01293   Serializer de_ser(&mb_in, false, Serializer::ALIGN_CDR);
01294   ACE_CDR::Octet type, flags;
01295   de_ser >> ACE_InputCDR::to_octet(type);
01296   de_ser >> ACE_InputCDR::to_octet(flags);
01297   de_ser.swap_bytes((flags & 1) != ACE_CDR_BYTE_ORDER);
01298   ACE_CDR::UShort octetsToNext;
01299   de_ser >> octetsToNext;
01300   CryptoHeader ch;
01301   de_ser.swap_bytes(Serializer::SWAP_BE);
01302   de_ser >> ch;
01303 
01304   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
01305   typedef std::multimap<ParticipantCryptoHandle, EntityInfo>::iterator iter_t;
01306   const std::pair<iter_t, iter_t> iters =
01307     participant_to_entity_.equal_range(sending_participant_crypto);
01308   for (iter_t iter = iters.first; iter != iters.second; ++iter) {
01309     const NativeCryptoHandle sending_entity_candidate = iter->second.handle_;
01310     if (keys_.count(sending_entity_candidate)) {
01311       const KeySeq& keyseq = keys_[sending_entity_candidate];
01312       for (unsigned int i = 0; i < keyseq.length(); ++i) {
01313         if (matches(keyseq[i], ch)) {
01314           secure_submessage_category = iter->second.category_;
01315           switch (secure_submessage_category) {
01316           case DATAWRITER_SUBMESSAGE:
01317             datawriter_crypto = iter->second.handle_;
01318             break;
01319           case DATAREADER_SUBMESSAGE:
01320             datareader_crypto = iter->second.handle_;
01321             break;
01322           default:
01323             break;
01324           }
01325           return true;
01326         }
01327       }
01328     }
01329   }
01330   CommonUtilities::set_security_error(ex, -2, 1, "Crypto Key not registered",
01331                                       ch.transform_identifier.transformation_kind,
01332                                       ch.transform_identifier.transformation_key_id);
01333   return false;
01334 }
01335 
01336 KeyOctetSeq
01337 CryptoBuiltInImpl::Session::get_key(const KeyMaterial& master,
01338                                     const CryptoHeader& header)
01339 {
01340   if (key_.length() && 0 == std::memcmp(&id_, &header.session_id, sizeof id_)) {
01341     return key_;
01342   }
01343   std::memcpy(&id_, &header.session_id, sizeof id_);
01344   key_.length(0);
01345   derive_key(master);
01346   return key_;
01347 }
01348 
01349 void CryptoBuiltInImpl::Session::derive_key(const KeyMaterial& master)
01350 {
01351   PrivateKey pkey(master.master_sender_key);
01352   DigestContext ctx;
01353   const EVP_MD* md = EVP_get_digestbyname("SHA256");
01354 
01355   if (EVP_DigestInit_ex(ctx, md, 0) < 1) {
01356     return;
01357   }
01358 
01359   if (EVP_DigestSignInit(ctx, 0, md, 0, pkey) < 1) {
01360     return;
01361   }
01362 
01363   static const char cookie[] = "SessionKey"; // DDSSEC12-53: NUL excluded
01364   if (EVP_DigestSignUpdate(ctx, cookie, (sizeof cookie) - 1) < 1) {
01365     return;
01366   }
01367 
01368   const KeyOctetSeq& salt = master.master_salt;
01369   if (EVP_DigestSignUpdate(ctx, salt.get_buffer(), salt.length()) < 1) {
01370     return;
01371   }
01372 
01373   if (EVP_DigestSignUpdate(ctx, id_, sizeof id_) < 1) {
01374     return;
01375   }
01376 
01377   size_t req = 0;
01378   if (EVP_DigestSignFinal(ctx, 0, &req) < 1) {
01379     return;
01380   }
01381 
01382   key_.length(static_cast<unsigned int>(req));
01383   if (EVP_DigestSignFinal(ctx, key_.get_buffer(), &req) < 1) {
01384     key_.length(0);
01385   }
01386 }
01387 
01388 bool CryptoBuiltInImpl::decrypt(const KeyMaterial& master, Session& sess,
01389                                 const char* ciphertext, unsigned int n,
01390                                 const CryptoHeader& header,
01391                                 const CryptoFooter& footer, DDS::OctetSeq& out,
01392                                 SecurityException& ex)
01393 
01394 {
01395   const KeyOctetSeq sess_key = sess.get_key(master, header);
01396   if (!sess_key.length()) {
01397     CommonUtilities::set_security_error(ex, -1, 0, "no session key");
01398     return false;
01399   }
01400 
01401   if (master.transformation_kind[TransformKindIndex] !=
01402       CRYPTO_TRANSFORMATION_KIND_AES256_GCM) {
01403     CommonUtilities::set_security_error(ex, -1, 0,
01404                                         "unsupported transformation kind");
01405     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::decrypt - ERROR "
01406                "unsupported transformation kind %d\n",
01407                master.transformation_kind[TransformKindIndex]));
01408     return false;
01409   }
01410 
01411   CipherContext ctx;
01412   // session_id is start of IV contiguous bytes
01413   if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), 0, sess_key.get_buffer(),
01414                          header.session_id) != 1) {
01415     CommonUtilities::set_security_error(ex, -1, 0, "EVP_DecryptInit_ex");
01416     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::decrypt - ERROR "
01417                "EVP_DecryptInit_ex %Ld\n", ERR_peek_last_error()));
01418     return false;
01419   }
01420 
01421   out.length(n + KEY_LEN_BYTES);
01422   int len;
01423   if (EVP_DecryptUpdate(ctx, out.get_buffer(), &len,
01424                         reinterpret_cast<const unsigned char*>(ciphertext), n)
01425       != 1) {
01426     CommonUtilities::set_security_error(ex, -1, 0, "EVP_DecryptUpdate");
01427     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::decrypt - ERROR "
01428                "EVP_DecryptUpdate %Ld\n", ERR_peek_last_error()));
01429     return false;
01430   }
01431 
01432   void* tag = const_cast<void*>(static_cast<const void*>(footer.common_mac));
01433   if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) {
01434     CommonUtilities::set_security_error(ex, -1, 0, "EVP_CIPHER_CTX_ctrl");
01435     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::decrypt - ERROR "
01436                "EVP_CIPHER_CTX_ctrl %Ld\n", ERR_peek_last_error()));
01437     return false;
01438   }
01439 
01440   int len2;
01441   if (EVP_DecryptFinal_ex(ctx, out.get_buffer() + len, &len2) == 1) {
01442     out.length(len + len2);
01443     return true;
01444   }
01445   CommonUtilities::set_security_error(ex, -1, 0, "EVP_DecryptFinal_ex");
01446   ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::decrypt - ERROR "
01447              "EVP_DecryptFinal_ex %Ld\n", ERR_peek_last_error()));
01448   return false;
01449 }
01450 
01451 bool CryptoBuiltInImpl::verify(const KeyMaterial& master, Session& sess,
01452                                const char* in, unsigned int n,
01453                                const CryptoHeader& header,
01454                                const CryptoFooter& footer, DDS::OctetSeq& out,
01455                                SecurityException& ex)
01456 
01457 {
01458   const KeyOctetSeq sess_key = sess.get_key(master, header);
01459   if (!sess_key.length()) {
01460     CommonUtilities::set_security_error(ex, -1, 0, "no session key");
01461     return false;
01462   }
01463 
01464   if (master.transformation_kind[TransformKindIndex] !=
01465       CRYPTO_TRANSFORMATION_KIND_AES256_GMAC) {
01466     CommonUtilities::set_security_error(ex, -1, 0,
01467                                         "unsupported transformation kind");
01468     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::verify - ERROR "
01469                "unsupported transformation kind %d\n",
01470                master.transformation_kind[TransformKindIndex]));
01471     return false;
01472   }
01473 
01474   CipherContext ctx;
01475   // session_id is start of IV contiguous bytes
01476   if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), 0, sess_key.get_buffer(),
01477                          header.session_id) != 1) {
01478     CommonUtilities::set_security_error(ex, -1, 0, "EVP_DecryptInit_ex");
01479     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::verify - ERROR "
01480                "EVP_DecryptInit_ex %Ld\n", ERR_peek_last_error()));
01481     return false;
01482   }
01483 
01484   int len;
01485   if (EVP_DecryptUpdate(ctx, 0, &len,
01486                         reinterpret_cast<const unsigned char*>(in), n) != 1) {
01487     CommonUtilities::set_security_error(ex, -1, 0, "EVP_DecryptUpdate");
01488     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::verify - ERROR "
01489                "EVP_DecryptUpdate %Ld\n", ERR_peek_last_error()));
01490     return false;
01491   }
01492 
01493   void* tag = const_cast<void*>(static_cast<const void*>(footer.common_mac));
01494   if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) {
01495     CommonUtilities::set_security_error(ex, -1, 0, "EVP_CIPHER_CTX_ctrl");
01496     ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::verify - ERROR "
01497                "EVP_CIPHER_CTX_ctrl %Ld\n", ERR_peek_last_error()));
01498     return false;
01499   }
01500 
01501   int len2;
01502   if (EVP_DecryptFinal_ex(ctx, 0, &len2) == 1) {
01503     out.length(n);
01504     std::memcpy(out.get_buffer(), in, n);
01505     return true;
01506   }
01507   CommonUtilities::set_security_error(ex, -1, 0, "EVP_DecryptFinal_ex");
01508   ACE_ERROR((LM_ERROR, "(%P|%t) CryptoBuiltInImpl::verify - ERROR "
01509              "EVP_DecryptFinal_ex %Ld\n", ERR_peek_last_error()));
01510   return false;
01511 }
01512 
01513 bool CryptoBuiltInImpl::decode_submessage(
01514   DDS::OctetSeq& plain_rtps_submessage,
01515   const DDS::OctetSeq& encoded_rtps_submessage,
01516   NativeCryptoHandle sender_handle,
01517   SecurityException& ex)
01518 {
01519   ACE_Message_Block mb_in(to_mb(encoded_rtps_submessage.get_buffer()),
01520                           encoded_rtps_submessage.length());
01521   mb_in.wr_ptr(encoded_rtps_submessage.length());
01522   Serializer de_ser(&mb_in, false, Serializer::ALIGN_CDR);
01523   ACE_CDR::Octet type, flags;
01524   // SEC_PREFIX
01525   de_ser >> ACE_InputCDR::to_octet(type);
01526   de_ser >> ACE_InputCDR::to_octet(flags);
01527   de_ser.swap_bytes((flags & 1) != ACE_CDR_BYTE_ORDER);
01528   ACE_CDR::UShort octetsToNext;
01529   de_ser >> octetsToNext;
01530   CryptoHeader ch;
01531   de_ser.swap_bytes(Serializer::SWAP_BE);
01532   de_ser >> ch;
01533   de_ser.skip(octetsToNext - CRYPTO_HEADER_LENGTH);
01534   // Next submessage, SEC_BODY if encrypted
01535   de_ser >> ACE_InputCDR::to_octet(type);
01536   de_ser >> ACE_InputCDR::to_octet(flags);
01537   de_ser.swap_bytes((flags & 1) != ACE_CDR_BYTE_ORDER);
01538   de_ser >> octetsToNext;
01539   Message_Block_Ptr mb_footer(mb_in.duplicate());
01540   mb_footer->rd_ptr(octetsToNext);
01541   // SEC_POSTFIX
01542   Serializer post_ser(mb_footer.get(), false, Serializer::ALIGN_CDR);
01543   post_ser >> ACE_InputCDR::to_octet(type);
01544   post_ser >> ACE_InputCDR::to_octet(flags);
01545   post_ser.swap_bytes((flags & 1) != ACE_CDR_BYTE_ORDER);
01546   ACE_CDR::UShort postfixOctetsToNext;
01547   post_ser >> postfixOctetsToNext;
01548   CryptoFooter cf;
01549   post_ser.swap_bytes(Serializer::SWAP_BE);
01550   post_ser >> cf;
01551 
01552   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
01553   const KeySeq& keyseq = keys_[sender_handle];
01554   for (unsigned int i = 0; i < keyseq.length(); ++i) {
01555     if (matches(keyseq[i], ch)) {
01556       const KeyId_t sKey = std::make_pair(sender_handle, i);
01557       if (encrypts(keyseq[i])) {
01558         de_ser.swap_bytes(Serializer::SWAP_BE);
01559         ACE_CDR::ULong n;
01560         de_ser >> n;
01561         return decrypt(keyseq[i], sessions_[sKey], mb_in.rd_ptr(), n, ch, cf,
01562                        plain_rtps_submessage, ex);
01563       } else if (authenticates(keyseq[i])) {
01564         return verify(keyseq[i], sessions_[sKey], mb_in.rd_ptr() - RTPS::SMHDR_SZ,
01565                       RTPS::SMHDR_SZ + octetsToNext, ch, cf, plain_rtps_submessage, ex);
01566       } else {
01567         CommonUtilities::set_security_error(ex, -2, 2, "Key transform "
01568                                             "kind unrecognized");
01569         return false;
01570       }
01571     }
01572   }
01573 
01574   CommonUtilities::set_security_error(ex, -2, 1, "Crypto Key not found");
01575   return false;
01576 }
01577 
01578 bool CryptoBuiltInImpl::decode_datawriter_submessage(
01579   DDS::OctetSeq& plain_rtps_submessage,
01580   const DDS::OctetSeq& encoded_rtps_submessage,
01581   DatareaderCryptoHandle /*receiving_datareader_crypto*/,
01582   DatawriterCryptoHandle sending_datawriter_crypto,
01583   SecurityException& ex)
01584 {
01585   // Allowing Nil Handle for receiver since origin auth is not implemented:
01586   //  if (DDS::HANDLE_NIL == receiving_datareader_crypto) {
01587   //CommonUtilities::set_security_error(ex, -1, 0, "Invalid Datareader handle");
01588   //    return false;
01589   //  }
01590   if (DDS::HANDLE_NIL == sending_datawriter_crypto) {
01591     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Datawriter handle");
01592     return false;
01593   }
01594 
01595   return decode_submessage(plain_rtps_submessage, encoded_rtps_submessage,
01596                            sending_datawriter_crypto, ex);
01597 }
01598 
01599 bool CryptoBuiltInImpl::decode_datareader_submessage(
01600   DDS::OctetSeq& plain_rtps_submessage,
01601   const DDS::OctetSeq& encoded_rtps_submessage,
01602   DatawriterCryptoHandle /*receiving_datawriter_crypto*/,
01603   DatareaderCryptoHandle sending_datareader_crypto,
01604   SecurityException& ex)
01605 {
01606   if (DDS::HANDLE_NIL == sending_datareader_crypto) {
01607     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Datareader handle");
01608     return false;
01609   }
01610   // Allowing Nil Handle for receiver since origin auth is not implemented:
01611   //  if (DDS::HANDLE_NIL == receiving_datawriter_crypto) {
01612   //CommonUtilities::set_security_error(ex, -1, 0, "Invalid Datawriter handle");
01613   //    return false;
01614   //  }
01615 
01616   return decode_submessage(plain_rtps_submessage, encoded_rtps_submessage,
01617                            sending_datareader_crypto, ex);
01618 }
01619 
01620 bool CryptoBuiltInImpl::decode_serialized_payload(
01621   DDS::OctetSeq& plain_buffer,
01622   const DDS::OctetSeq& encoded_buffer,
01623   const DDS::OctetSeq& /*inline_qos*/,
01624   DatareaderCryptoHandle /*receiving_datareader_crypto*/,
01625   DatawriterCryptoHandle sending_datawriter_crypto,
01626   SecurityException& ex)
01627 {
01628   // Not currently requring a reader handle here, origin authentication
01629   // for data payloads is not supported.
01630   // if (DDS::HANDLE_NIL == receiving_datareader_crypto) {
01631   //   CommonUtilities::set_security_error(ex, -1, 0, "Invalid Datareader handle");
01632   //   return false;
01633   // }
01634   if (DDS::HANDLE_NIL == sending_datawriter_crypto) {
01635     CommonUtilities::set_security_error(ex, -1, 0, "Invalid Datawriter handle");
01636     return false;
01637   }
01638 
01639   ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
01640   if (!writer_options_[sending_datawriter_crypto].payload_) {
01641     plain_buffer = encoded_buffer;
01642     return true;
01643   }
01644 
01645   ACE_Message_Block mb_in(to_mb(encoded_buffer.get_buffer()),
01646                           encoded_buffer.length());
01647   mb_in.wr_ptr(encoded_buffer.length());
01648   Serializer de_ser(&mb_in, Serializer::SWAP_BE, Serializer::ALIGN_CDR);
01649   CryptoHeader ch;
01650   de_ser >> ch;
01651 
01652   const KeySeq& keyseq = keys_[sending_datawriter_crypto];
01653   for (unsigned int i = 0; i < keyseq.length(); ++i) {
01654     if (matches(keyseq[i], ch)) {
01655       const KeyId_t sKey = std::make_pair(sending_datawriter_crypto, i);
01656       if (encrypts(keyseq[i])) {
01657         ACE_CDR::ULong n;
01658         de_ser >> n;
01659         const char* ciphertext = mb_in.rd_ptr();
01660         de_ser.skip(n);
01661         CryptoFooter cf;
01662         de_ser >> cf;
01663         return decrypt(keyseq[i], sessions_[sKey], ciphertext, n, ch, cf,
01664                        plain_buffer, ex);
01665       } else if (authenticates(keyseq[i])) {
01666         CommonUtilities::set_security_error(ex, -3, 3, "Auth-only payload "
01667                                             "transformation not supported "
01668                                             "(DDSSEC12-59)");
01669         return false;
01670       } else {
01671         CommonUtilities::set_security_error(ex, -3, 2,
01672                                             "Key transform kind unrecognized");
01673         return false;
01674       }
01675     }
01676   }
01677 
01678   CommonUtilities::set_security_error(ex, -3, 1, "Crypto Key not found");
01679   return false;
01680 }
01681 
01682 }
01683 }
01684 
01685 OPENDDS_END_VERSIONED_NAMESPACE_DECL
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 9 Aug 2018 for OpenDDS by  doxygen 1.6.1