00001
00002
00003
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"
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
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
00206
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);
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
00313
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 ,
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
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
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
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
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
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& ,
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
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
01020
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;
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;
01057 }
01058
01059 size += pOut->length();
01060 if ((size + padding) % 4) {
01061 padding += 4 - ((size + padding) % 4);
01062 }
01063
01064 size += 4;
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
01117
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
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
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
01226
01227 DDS::OctetSeq transformed_buffer(plain_rtps_message);
01228 encoded_rtps_message.swap(transformed_buffer);
01229
01230
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
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
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";
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
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
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
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
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
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 ,
01582 DatawriterCryptoHandle sending_datawriter_crypto,
01583 SecurityException& ex)
01584 {
01585
01586
01587
01588
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 ,
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
01611
01612
01613
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& ,
01624 DatareaderCryptoHandle ,
01625 DatawriterCryptoHandle sending_datawriter_crypto,
01626 SecurityException& ex)
01627 {
01628
01629
01630
01631
01632
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