DDS Security built-in Cryptographic plugin (#306)

* DDS Security built-in Cryptographic plugin

This commit adds the built-in Cryptographic plugin that is part of the
DDS Security implementation for Cyclone.

The Cryptographic plugin defines the types and operations necessary
to support encryption, digest, message authentication codes, and key
exchange for DDS DomainParticipants, DataWriters and DDS DataReaders.

Similar to other builtin plugins, the DDS Security cryptographic plugin
is built as a shared library to allow dynamic library loading on runtime.
This enables DDS participants to use specific plugin implementations
with different configurations.

Although I think this initial version is a reasonable starting point to be
merged in the security branch, some parts of the code will need refactoring:

* crypto_key_factory.c: crypto_factory_get_endpoint_relation returns
arbitrary local-remote relation if no specific key for remote is found,
which will not work in Cyclone because participants can have different
security settings

* performance of encoding data can be improved by not copying
plain_rtps_message to a new buffer (to enable this, crypto_cipher_encrypt_data
should allow encrypting parts of a message)

* when decoding a message the message is split in several parts (header, body,
footer, etc) and for this memory is allocated which is probably not necessary.
Performance should be improved by removing these allocations and use pointers
to the data instead.

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* WIP processing crypto plugin review comments

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* WIP more refactoring based on review comments

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* WIP fixing crypto plugin support for 128 bit key size

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* WIP refactored master key storage to reduce memory usage when using 128 bit keys

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* WIP fixing windows build linker issue

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* WIP refactored crypto key types, avoid returning pointers to released ref-counted object

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* Fixed bug in test decode_datareader_submessage.invalid_data

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* Fixed issues from review: use correct constant for hashing and handle different src/dst keysize correctly

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
This commit is contained in:
Dennis Potman 2019-12-05 10:30:35 +01:00 committed by eboasson
parent 37c64e0965
commit 30bd6e4c1c
54 changed files with 24804 additions and 272 deletions

View file

@ -0,0 +1,58 @@
#
# Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
include (GenerateExportHeader)
find_package(OpenSSL)
PREPEND(srcs_cryptographic "${CMAKE_CURRENT_LIST_DIR}/src"
crypto_cipher.c
crypto_key_exchange
crypto_key_factory.c
crypto_objects.c
crypto_transform.c
crypto_utils.c
cryptography.c
)
add_library(dds_security_crypto SHARED "")
generate_export_header(
dds_security_crypto
BASE_NAME SECURITY
EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h"
)
add_definitions(-DDDSI_INCLUDE_SSL)
target_link_libraries(dds_security_crypto PUBLIC ddsc)
target_link_libraries(dds_security_crypto PUBLIC OpenSSL::SSL)
target_sources(dds_security_crypto
PRIVATE
${srcs_cryptographic}
)
target_include_directories(dds_security_crypto
PUBLIC
"$<BUILD_INTERFACE:$<TARGET_PROPERTY:security_api,INTERFACE_INCLUDE_DIRECTORIES>>"
"$<BUILD_INTERFACE:$<TARGET_PROPERTY:security_core,INTERFACE_INCLUDE_DIRECTORIES>>"
"$<BUILD_INTERFACE:$<TARGET_PROPERTY:ddsrt,INTERFACE_INCLUDE_DIRECTORIES>>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
)
install(
TARGETS
EXPORT "${PROJECT_NAME}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
)

View file

@ -0,0 +1,258 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/types.h"
#include "crypto_defs.h"
#include "crypto_utils.h"
#include "crypto_cipher.h"
bool crypto_cipher_encrypt_data(
const crypto_session_key_t *session_key,
uint32_t key_size,
const unsigned char *iv,
const unsigned char *data,
uint32_t data_len,
const unsigned char *aad,
uint32_t aad_len,
unsigned char *encrypted,
uint32_t *encrypted_len,
crypto_hmac_t *tag,
DDS_Security_SecurityException *ex)
{
EVP_CIPHER_CTX *ctx;
int len = 0;
/* create the cipher context */
ctx = EVP_CIPHER_CTX_new();
if (!ctx)
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_CIPHER_CTX_new failed: ");
goto fail_ctx_new;
}
/* initialize the cipher and set to AES GCM */
if (key_size == 128)
{
if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptInit_ex to set aes_128_gcm failed: ");
goto fail_encrypt;
}
}
else if (key_size == 256)
{
if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptInit_ex to set aes_256_gcm failed: ");
goto fail_encrypt;
}
}
else
{
assert(0);
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptInit_ex invalid key size: %u", key_size);
goto fail_encrypt;
}
/* Initialise key and IV */
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, session_key->data, iv))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptInit_ex failed: ");
goto fail_encrypt;
}
if (aad)
{
if (aad_len > INT_MAX)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptUpdate to update aad failed: aad_len exceeds INT_MAX");
goto fail_encrypt;
}
/* Provide any AAD data */
if (!EVP_EncryptUpdate(ctx, NULL, &len, aad, (int) aad_len))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptUpdate to update aad failed: %s");
goto fail_encrypt;
}
}
if (data)
{
if (data_len > INT_MAX)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptUpdate to update data failed: data_len exceeds INT_MAX");
goto fail_encrypt;
}
/* encrypt the message */
if (!EVP_EncryptUpdate(ctx, encrypted, &len, data, (int) data_len))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptUpdate update data failed: ");
goto fail_encrypt;
}
assert (len >= 0); /* conform openssl spec */
*encrypted_len = (uint32_t) len;
}
/* finalize the encryption */
if (data)
{
if (!EVP_EncryptFinal_ex(ctx, encrypted + len, &len))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptFinal_ex to finalize encryption failed: ");
goto fail_encrypt;
}
assert (len >= 0); /* conform openssl spec */
*encrypted_len += (uint32_t) len;
}
else
{
unsigned char temp[32];
if (!EVP_EncryptFinal_ex(ctx, temp, &len))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_EncryptFinal_ex to finalize aad failed: ");
goto fail_encrypt;
}
}
/* get the tag */
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, CRYPTO_HMAC_SIZE, tag->data))
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_CIPHER_CTX_ctrl to get the tag failed: ");
goto fail_encrypt;
}
EVP_CIPHER_CTX_free(ctx);
return true;
fail_encrypt:
EVP_CIPHER_CTX_free(ctx);
fail_ctx_new:
return false;
}
bool crypto_cipher_decrypt_data(
const remote_session_info *session,
const unsigned char *iv,
const unsigned char *encrypted,
uint32_t encrypted_len,
const unsigned char *aad,
uint32_t aad_len,
unsigned char *data,
uint32_t *data_len,
crypto_hmac_t *tag,
DDS_Security_SecurityException *ex)
{
EVP_CIPHER_CTX *ctx;
int len = 0;
/* create the cipher context */
ctx = EVP_CIPHER_CTX_new();
if (!ctx)
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_CIPHER_CTX_new failed: ");
goto fail_ctx_new;
}
/* initialize the cipher and set to AES GCM */
if (session->key_size == 128)
{
if (EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1)
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_DecryptInit_ex to set aes_128_gcm failed: ");
goto fail_decrypt;
}
}
else if (session->key_size == 256)
{
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_DecryptInit_ex to set aes_256_gcm failed: ");
goto fail_decrypt;
}
}
else
{
assert(0);
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "Internal key_size is not correct: %u", session->key_size);
goto fail_decrypt;
}
/* Initialise key and IV */
if (EVP_DecryptInit_ex(ctx, NULL, NULL, session->key.data, iv) != 1)
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_DecryptInit_ex to set aes_256_gcm failed: %s");
goto fail_decrypt;
}
if (aad)
{
assert (aad_len <= INT32_MAX);
/* Provide any AAD data for signature */
if (EVP_DecryptUpdate(ctx, NULL, &len, aad, (int) aad_len) != 1)
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_DecryptUpdate to update aad failed: ");
goto fail_decrypt;
}
}
/* Set expected tag value. */
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, CRYPTO_HMAC_SIZE, tag->data) != 1)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_CIPHER_CTX_ctrl to get tag failed: ");
goto fail_decrypt;
}
if (data)
{
/* decrypt the message */
if (EVP_DecryptUpdate(ctx, data, &len, encrypted, (int) encrypted_len) != 1)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_DecryptUpdate update data failed: ");
goto fail_decrypt;
}
assert (len >= 0);
*data_len = (uint32_t)len;
}
if (data)
{
if (EVP_DecryptFinal_ex(ctx, data + len, &len) != 1)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_DecryptFinal_ex to finalize decryption failed: ");
goto fail_decrypt;
}
assert (len >= 0);
*data_len += (uint32_t)len;
}
else
{
unsigned char temp[32];
if (EVP_DecryptFinal_ex(ctx, temp, &len) != 1)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "EVP_DecryptFinal_ex to finalize signature check failed: ");
goto fail_decrypt;
}
}
EVP_CIPHER_CTX_free(ctx);
return true;
fail_decrypt:
EVP_CIPHER_CTX_free(ctx);
fail_ctx_new:
return false;
}

View file

@ -0,0 +1,99 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTO_CIPHER_H
#define CRYPTO_CIPHER_H
#include "dds/ddsrt/types.h"
#include "crypto_objects.h"
/**
* @brief Encodes the provide data using the provided key
*
* This function encodes the provide data using the provided key, key_size
* and initialization_vector. It also computes the common_mac from the provided data.
* The data parameter contains the data that has to encoded. The aad parameter contains
* the data that is not encoded but is used in the computation of the common_mac
* On return the encrypted parameter contains the encoded data and the tag parameter
* the common mac.
* This function will be used either to encode the provided data in that case the
* data parameter should be set to the data to be encoded and the aad parameter should
* be NULL. Also the encrypted parameter should be set and contain a buffer large enough
* to contain the encoded data.
* This function is also used to only computer the common_mac. In that case the
* data parameter should be NULL and the aad parameter should point to the data on
* which the common_mac has to be computed. The encryped parameter is not relevant
* in this case.
*
* @param[in] session_key The session key used to encode the provided data
* @param[in] key_size The size of the session key (128 or 256 bit)
* @param[in] iv The init vector used by the encoding
* @param[in] data The data to be encoded
* @param[in] data_len The size of the data to be encoded
* @param[in] aad The additional data not be encoded but only used in the computation of the mac
* @param[in] aad_len The size of the additional data
* @param[in,out] encrypted The buffer to hold on return the encoded data
* @param[in,out] encrypted_len The size of the encrypted data buffer
* @param[in,out] tag Contains on return the mac value calculated over the provided data
* @param[in,out] ex Security exception (optional)
*/
bool crypto_cipher_encrypt_data(
const crypto_session_key_t *session_key,
uint32_t key_size,
const unsigned char *iv,
const unsigned char *data,
uint32_t data_len,
const unsigned char *aad,
uint32_t aad_len,
unsigned char *encrypted,
uint32_t *encrypted_len,
crypto_hmac_t *tag,
DDS_Security_SecurityException *ex);
/**
* @brief Decodes the provided data using the session key and key_size
*
* This function decodes the provided data using the session key and key_size provided
* by by the session parameter. The iv parameter contains the initialization_vector used
* by the decode operation which is the concatination of received session_id and init_vector_suffix.
* The function checks if the common_mac (tag parameter) is corresponds with the provided data.
* This function will be used either to decode the provided data in that case the
* encrypted parameter should be set to the data to be decoded and the aad parameter should
* be NULL. Also the data parameter should be set and contain a buffer large enough
* to contain the decoded data.
* This function is also used to only verify the common_mac. In that case the
* data and the encrypted parameter should be NULL and the aad parameter should point to
* the data for which the common_mac has to be verified.
*
* @param[in] session Contains the session key and key size used of the decoding
* @param[in] iv The init vector used by the decoding
* @param[in] encrypted The encoded data
* @param[in] encrypted_len The size of the encoded data
* @param[in] aad The not encoded data used in the verification of the provided mac
* @param[in] aad_len The size of the additional data
* @param[in,out] data The buffer to hold on return the decoded data
* @param[in,out] data_len The size of the decoded data buffer
* @param[in,out] tag The mac value which has to be verified
* @param[in,out] ex Security exception (optional)
*/
bool crypto_cipher_decrypt_data(
const remote_session_info *session,
const unsigned char *iv,
const unsigned char *encrypted,
uint32_t encrypted_len,
const unsigned char *aad,
uint32_t aad_len,
unsigned char *data,
uint32_t *data_len,
crypto_hmac_t *tag,
DDS_Security_SecurityException *ex);
#endif /* CRYPTO_CIPHER_H */

View file

@ -0,0 +1,114 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTO_DEFS_H
#define CRYPTO_DEFS_H
#include "dds/security/dds_security_api.h"
#define DDS_CRYPTO_PLUGIN_CONTEXT "Cryptographic"
#define CRYPTO_HMAC_SIZE 16
#define CRYPTO_KEY_SIZE_128 16
#define CRYPTO_KEY_SIZE_256 32
#define CRYPTO_KEY_SIZE_MAX CRYPTO_KEY_SIZE_256
#define CRYPTO_SESSION_ID_SIZE 4
#define CRYPTO_INIT_VECTOR_SUFFIX_SIZE 8
#define CRYPTO_CIPHER_BLOCK_SIZE 16
typedef enum SecureSubmsgKind_t
{
SMID_SEC_BODY_KIND = 0x30,
SMID_SEC_PREFIX_KIND = 0x31,
SMID_SEC_POSTFIX_KIND = 0x32,
SMID_SRTPS_PREFIX_KIND = 0x33,
SMID_SRTPS_POSTFIX_KIND = 0x34,
SMID_SRTPS_INFO_SRC_KIND = 0x0c
} SecureSubmsgKind_t;
typedef struct crypto_session_key_t
{
unsigned char data[CRYPTO_KEY_SIZE_MAX];
} crypto_session_key_t;
typedef struct crypto_hmac_t
{
unsigned char data[CRYPTO_HMAC_SIZE];
} crypto_hmac_t;
typedef enum RTPS_Message_Type
{
/** The Constant PAD. */
RTPS_Message_Type_PAD = 0x01,
/** The Constant ACKNACK. */
RTPS_Message_Type_ACKNACK = 0x06,
/** The Constant HEARTBEAT. */
RTPS_Message_Type_HEARTBEAT = 0x07,
/** The Constant GAP. */
RTPS_Message_Type_GAP = 0x08,
/** The Constant INFO_TS. */
RTPS_Message_Type_INFO_TS = 0x09,
/** The Constant INFO_SRC. */
RTPS_Message_Type_INFO_SRC = 0x0c,
/** The Constant INFO_REPLY_IP4. */
RTPS_Message_Type_INFO_REPLY_IP4 = 0x0d,
/** The Constant INFO_DST. */
RTPS_Message_Type_INFO_DST = 0x0e,
/** The Constant INFO_REPLY. */
RTPS_Message_Type_INFO_REPLY = 0x0f,
/** The Constant NACK_FRAG. */
RTPS_Message_Type_NACK_FRAG = 0x12,
/** The Constant HEARTBEAT_FRAG. */
RTPS_Message_Type_HEARTBEAT_FRAG = 0x13,
/** The Constant DATA. */
RTPS_Message_Type_DATA = 0x15,
/** The Constant DATA_FRAG. */
RTPS_Message_Type_DATA_FRAG = 0x16,
/** The Constant MSG_LENGTH. */
RTPS_Message_Type_MSG_LEN = 0x81,
/** The Constant MSG_ENTITY_ID. */
RTPS_Message_Type_MSG_ENTITY_ID = 0x82,
/** The Constant INFO_LASTHB. */
RTPS_Message_Type_INFO_LASTHB = 0x83,
/** The Constant SEC_PREFIX. */
RTPS_Message_Type_SEC_BODY = 0x30,
/** The Constant SEC_PREFIX. */
RTPS_Message_Type_SEC_PREFIX = 0x31,
/** The Constant SEC_POSTFIX. */
RTPS_Message_Type_SEC_POSTFIX = 0x32,
/** The Constant SRTPS_PREFIX. */
RTPS_Message_Type_SRTPS_PREFIX = 0x33,
/** The Constant SRTPS_POSTFIX. */
RTPS_Message_Type_SRTPS_POSTFIX = 0x34
} RTPS_Message_Type;
#endif /* CRYPTO_DEFS_H */

View file

@ -0,0 +1,538 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <string.h>
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/string.h"
#include "dds/ddsrt/types.h"
#include "dds/security/dds_security_api.h"
#include "dds/security/core/dds_security_utils.h"
#include "dds/security/core/dds_security_serialize.h"
#include "crypto_defs.h"
#include "crypto_utils.h"
#include "cryptography.h"
#include "crypto_key_exchange.h"
#include "crypto_key_factory.h"
static const char *CRYPTO_TOKEN_CLASS_ID = "DDS:Crypto:AES_GCM_GMAC";
static const char *CRYPTO_TOKEN_PROPERTY_NAME = "dds.cryp.keymat";
/**
* Implementation structure for storing encapsulated members of the instance
* while giving only the interface definition to user
*/
typedef struct dds_security_crypto_key_exchange_impl
{
dds_security_crypto_key_exchange base;
const dds_security_cryptography *crypto;
} dds_security_crypto_key_exchange_impl;
static bool check_crypto_tokens(const DDS_Security_DataHolderSeq *tokens)
{
bool status = true;
uint32_t i;
if (tokens->_length == 0 || tokens->_buffer == NULL)
status = false;
for (i = 0; status && (i < tokens->_length); i++)
{
status = (tokens->_buffer[i].class_id != NULL) &&
(strcmp(CRYPTO_TOKEN_CLASS_ID, tokens->_buffer[i].class_id) == 0) &&
(tokens->_buffer[i].binary_properties._length == 1) &&
(tokens->_buffer[i].binary_properties._buffer != NULL) &&
(tokens->_buffer[i].binary_properties._buffer[0].name != NULL) &&
(strcmp(CRYPTO_TOKEN_PROPERTY_NAME, tokens->_buffer[i].binary_properties._buffer[0].name) == 0) &&
(tokens->_buffer[i].binary_properties._buffer[0].value._length > 0) &&
(tokens->_buffer[i].binary_properties._buffer[0].value._buffer != NULL);
}
return status;
}
static bool check_not_data_empty(const DDS_Security_OctetSeq *seq)
{
uint32_t i;
for (i = 0; i < seq->_length; i++)
{
if (seq->_buffer[i] != 0)
return true;
}
return false;
}
static bool check_crypto_keymaterial(const DDS_Security_KeyMaterial_AES_GCM_GMAC *keymat)
{
bool status;
uint32_t transform_kind = CRYPTO_TRANSFORM_KIND(keymat->transformation_kind);
uint32_t key_sz = CRYPTO_KEY_SIZE_BYTES(transform_kind);
status = (transform_kind >= CRYPTO_TRANSFORMATION_KIND_AES128_GMAC && transform_kind <= CRYPTO_TRANSFORMATION_KIND_AES256_GCM &&
keymat->master_salt._length == key_sz && keymat->master_salt._buffer != NULL && check_not_data_empty(&keymat->master_salt) &&
keymat->master_sender_key._length == key_sz && keymat->master_sender_key._buffer != NULL && check_not_data_empty(&keymat->master_sender_key));
if (status && CRYPTO_TRANSFORM_ID(keymat->receiver_specific_key_id))
{
status = (keymat->master_receiver_specific_key._length == key_sz &&
keymat->master_receiver_specific_key._buffer != NULL && check_not_data_empty(&keymat->master_receiver_specific_key));
}
return status;
}
// serialized_key_material
// {
// uint32_t transformation_kind
// uint32_t master_salt_len
// uint8_t[SALT_SIZE] master_salt
// uint32_t sender_key_id
// uint32_t master_sender_key_len
// uint8_t[KEY_SIZE] master_sender_key
// uint32_t receiver_specific_key_id
// uint32_t master_receiver_specific_key_len
// uint8_t[KEY_SIZE] master_receiver_specific_key
// }
static void
serialize_master_key_material(
const master_key_material *keymat,
uint8_t **buffer,
uint32_t *length)
{
uint32_t *sd;
size_t i = 0;
uint32_t key_bytes = CRYPTO_KEY_SIZE_BYTES(keymat->transformation_kind);
size_t sz = 6 * sizeof (uint32_t) + 2 * key_bytes;
if (keymat->receiver_specific_key_id)
sz += key_bytes;
*buffer = ddsrt_malloc(sz);
*length = (uint32_t)sz;
sd = (uint32_t *)(*buffer);
sd[i++] = ddsrt_toBE4u(keymat->transformation_kind);
sd[i++] = ddsrt_toBE4u(key_bytes);
memcpy(&sd[i], keymat->master_salt, key_bytes);
i += key_bytes / sizeof (uint32_t);
sd[i++] = ddsrt_toBE4u(keymat->sender_key_id);
sd[i++] = ddsrt_toBE4u(key_bytes);
memcpy(&sd[i], keymat->master_sender_key, key_bytes);
i += key_bytes / sizeof (uint32_t);
sd[i++] = ddsrt_toBE4u(keymat->receiver_specific_key_id);
if (keymat->receiver_specific_key_id)
{
sd[i++] = ddsrt_toBE4u(key_bytes);
memcpy(&sd[i], keymat->master_receiver_specific_key, key_bytes);
}
else
{
sd[i++] = ddsrt_toBE4u(0);
}
}
/**
* Function implementations
*/
static DDS_Security_boolean
create_local_participant_crypto_tokens(
dds_security_crypto_key_exchange *instance,
DDS_Security_ParticipantCryptoTokenSeq *tokens,
const DDS_Security_ParticipantCryptoHandle local_id,
const DDS_Security_ParticipantCryptoHandle remote_id,
DDS_Security_SecurityException *ex)
{
dds_security_crypto_key_exchange_impl *impl = (dds_security_crypto_key_exchange_impl *)instance;
dds_security_crypto_key_factory *factory;
participant_key_material *pp_key_material;
uint8_t *buffer;
uint32_t length;
if (!instance || !tokens || local_id == 0 || remote_id == 0)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"create_local_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
goto fail_invalid_arg;
}
factory = cryptography_get_crypto_key_factory(impl->crypto);
if (!crypto_factory_get_participant_crypto_tokens(factory, local_id, remote_id, &pp_key_material, NULL, ex))
goto fail_invalid_arg;
serialize_master_key_material(pp_key_material->local_P2P_key_material, &buffer, &length);
CRYPTO_OBJECT_RELEASE(pp_key_material);
tokens->_buffer = DDS_Security_DataHolderSeq_allocbuf(1);
tokens->_length = tokens->_maximum = 1;
tokens->_buffer[0].class_id = ddsrt_strdup(CRYPTO_TOKEN_CLASS_ID);
tokens->_buffer[0].binary_properties._buffer = DDS_Security_BinaryPropertySeq_allocbuf(1);
tokens->_buffer[0].binary_properties._length = tokens->_buffer[0].binary_properties._maximum = 1;
tokens->_buffer[0].binary_properties._buffer[0].name = ddsrt_strdup(CRYPTO_TOKEN_PROPERTY_NAME);
tokens->_buffer[0].binary_properties._buffer[0].value._length =
tokens->_buffer[0].binary_properties._buffer[0].value._maximum = length;
tokens->_buffer[0].binary_properties._buffer[0].value._buffer = buffer;
return true;
fail_invalid_arg:
return false;
}
static DDS_Security_boolean
set_remote_participant_crypto_tokens(
dds_security_crypto_key_exchange *instance,
const DDS_Security_ParticipantCryptoHandle local_id,
const DDS_Security_ParticipantCryptoHandle remote_id,
const DDS_Security_ParticipantCryptoTokenSeq *tokens,
DDS_Security_SecurityException *ex)
{
DDS_Security_boolean result = false;
dds_security_crypto_key_exchange_impl *impl = (dds_security_crypto_key_exchange_impl *)instance;
dds_security_crypto_key_factory *factory;
DDS_Security_KeyMaterial_AES_GCM_GMAC remote_key_mat;
const DDS_Security_OctetSeq *tdata;
DDS_Security_Deserializer deserializer;
if (!instance || !tokens || local_id == 0 || remote_id == 0)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
if (!check_crypto_tokens(tokens))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
tdata = &tokens->_buffer[0].binary_properties._buffer[0].value;
deserializer = DDS_Security_Deserializer_new(tdata->_buffer, tdata->_length);
if (!deserializer)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else if (!DDS_Security_Deserialize_KeyMaterial_AES_GCM_GMAC(deserializer, &remote_key_mat))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else if (!check_crypto_keymaterial(&remote_key_mat))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else
{
factory = cryptography_get_crypto_key_factory(impl->crypto);
result = crypto_factory_set_participant_crypto_tokens(factory, local_id, remote_id, &remote_key_mat, ex);
DDS_Security_KeyMaterial_AES_GCM_GMAC_deinit(&remote_key_mat);
}
DDS_Security_Deserializer_free(deserializer);
return result;
}
static DDS_Security_boolean
create_local_datawriter_crypto_tokens(
dds_security_crypto_key_exchange *instance,
DDS_Security_DatawriterCryptoTokenSeq *tokens,
const DDS_Security_DatawriterCryptoHandle local_writer_handle,
const DDS_Security_DatareaderCryptoHandle remote_reader_handle,
DDS_Security_SecurityException *ex)
{
dds_security_crypto_key_exchange_impl *impl = (dds_security_crypto_key_exchange_impl *)instance;
dds_security_crypto_key_factory *factory;
master_key_material *key_mat[2];
uint32_t num_key_mat = 2;
uint32_t i;
if (!instance || !tokens || local_writer_handle == DDS_SECURITY_HANDLE_NIL || remote_reader_handle == DDS_SECURITY_HANDLE_NIL)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"create_local_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
factory = cryptography_get_crypto_key_factory(impl->crypto);
if (!crypto_factory_get_datawriter_crypto_tokens(factory, local_writer_handle, remote_reader_handle, key_mat, &num_key_mat, ex))
return false;
tokens->_length = tokens->_maximum = num_key_mat;
tokens->_buffer = (num_key_mat > 0) ? DDS_Security_DataHolderSeq_allocbuf(num_key_mat) : NULL;
for (i = 0; i < num_key_mat; i++)
{
uint8_t *buffer;
uint32_t length;
serialize_master_key_material(key_mat[i], &buffer, &length);
tokens->_buffer[i].class_id = ddsrt_strdup(CRYPTO_TOKEN_CLASS_ID);
tokens->_buffer[i].binary_properties._buffer = DDS_Security_BinaryPropertySeq_allocbuf(1);
tokens->_buffer[i].binary_properties._length = tokens->_buffer[0].binary_properties._maximum = 1;
tokens->_buffer[i].binary_properties._buffer[0].name = ddsrt_strdup(CRYPTO_TOKEN_PROPERTY_NAME);
tokens->_buffer[i].binary_properties._buffer[0].value._length =
tokens->_buffer[i].binary_properties._buffer[0].value._maximum = length;
tokens->_buffer[i].binary_properties._buffer[0].value._buffer = buffer;
CRYPTO_OBJECT_RELEASE(key_mat[i]);
}
return true;
}
static DDS_Security_boolean
set_remote_datawriter_crypto_tokens(
dds_security_crypto_key_exchange *instance,
const DDS_Security_DatareaderCryptoHandle local_reader_handle,
const DDS_Security_DatawriterCryptoHandle remote_writer_handle,
const DDS_Security_DatawriterCryptoTokenSeq *tokens,
DDS_Security_SecurityException *ex)
{
DDS_Security_boolean result = true;
dds_security_crypto_key_exchange_impl *impl = (dds_security_crypto_key_exchange_impl *)instance;
dds_security_crypto_key_factory *factory;
DDS_Security_KeyMaterial_AES_GCM_GMAC remote_key_mat[2];
uint32_t i;
if (!instance || !tokens || local_reader_handle == DDS_SECURITY_HANDLE_NIL || remote_writer_handle == DDS_SECURITY_HANDLE_NIL)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
if (!check_crypto_tokens(tokens))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
if (tokens->_length > 2)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
for (i = 0; result && (i < tokens->_length); i++)
{
const DDS_Security_OctetSeq *tdata = &tokens->_buffer[i].binary_properties._buffer[0].value;
DDS_Security_Deserializer deserializer = DDS_Security_Deserializer_new(tdata->_buffer, tdata->_length);
if (!deserializer)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else if (!DDS_Security_Deserialize_KeyMaterial_AES_GCM_GMAC(deserializer, &remote_key_mat[i]))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else if (!check_crypto_keymaterial(&remote_key_mat[i]))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
DDS_Security_Deserializer_free(deserializer);
}
if (result)
{
factory = cryptography_get_crypto_key_factory(impl->crypto);
result = crypto_factory_set_datawriter_crypto_tokens(factory, local_reader_handle, remote_writer_handle, remote_key_mat, tokens->_length, ex);
}
for (i = 0; i < tokens->_length; i++)
DDS_Security_KeyMaterial_AES_GCM_GMAC_deinit(&remote_key_mat[i]);
return result;
}
static DDS_Security_boolean
create_local_datareader_crypto_tokens(
dds_security_crypto_key_exchange *instance,
DDS_Security_DatareaderCryptoTokenSeq *tokens,
const DDS_Security_DatareaderCryptoHandle local_reader_handle,
const DDS_Security_DatawriterCryptoHandle remote_writer_handle,
DDS_Security_SecurityException *ex)
{
dds_security_crypto_key_exchange_impl *impl = (dds_security_crypto_key_exchange_impl *)instance;
dds_security_crypto_key_factory *factory;
master_key_material *key_mat = NULL;
uint8_t *buffer;
uint32_t length;
if (!instance || !tokens || local_reader_handle == DDS_SECURITY_HANDLE_NIL || remote_writer_handle == DDS_SECURITY_HANDLE_NIL)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"create_local_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
factory = cryptography_get_crypto_key_factory(impl->crypto);
if (!crypto_factory_get_datareader_crypto_tokens(factory, local_reader_handle, remote_writer_handle, &key_mat, ex))
return false;
if (key_mat != NULL)
{ /* there may be no keymaterial according to configuration */
serialize_master_key_material(key_mat, &buffer, &length);
tokens->_buffer = DDS_Security_DataHolderSeq_allocbuf(1);
tokens->_length = tokens->_maximum = 1;
tokens->_buffer[0].class_id = ddsrt_strdup(CRYPTO_TOKEN_CLASS_ID);
tokens->_buffer[0].binary_properties._buffer = DDS_Security_BinaryPropertySeq_allocbuf(1);
tokens->_buffer[0].binary_properties._length = tokens->_buffer[0].binary_properties._maximum = 1;
tokens->_buffer[0].binary_properties._buffer[0].name = ddsrt_strdup(CRYPTO_TOKEN_PROPERTY_NAME);
tokens->_buffer[0].binary_properties._buffer[0].value._length =
tokens->_buffer[0].binary_properties._buffer[0].value._maximum = length;
tokens->_buffer[0].binary_properties._buffer[0].value._buffer = buffer;
CRYPTO_OBJECT_RELEASE(key_mat);
}
else
{
tokens->_buffer = NULL;
tokens->_length = 0;
tokens->_maximum = 0;
}
return true;
}
static DDS_Security_boolean
set_remote_datareader_crypto_tokens(
dds_security_crypto_key_exchange *instance,
const DDS_Security_DatawriterCryptoHandle local_writer_handle,
const DDS_Security_DatareaderCryptoHandle remote_reader_handle,
const DDS_Security_DatareaderCryptoTokenSeq *tokens,
DDS_Security_SecurityException *ex)
{
DDS_Security_boolean result = false;
dds_security_crypto_key_exchange_impl *impl = (dds_security_crypto_key_exchange_impl *)instance;
dds_security_crypto_key_factory *factory;
DDS_Security_KeyMaterial_AES_GCM_GMAC remote_key_mat;
const DDS_Security_OctetSeq *tdata;
DDS_Security_Deserializer deserializer;
if (!instance || !tokens || local_writer_handle == DDS_SECURITY_HANDLE_NIL || remote_reader_handle == DDS_SECURITY_HANDLE_NIL)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
if (!check_crypto_tokens(tokens))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
return false;
}
tdata = &tokens->_buffer[0].binary_properties._buffer[0].value;
deserializer = DDS_Security_Deserializer_new(tdata->_buffer, tdata->_length);
if (!deserializer)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else if (!DDS_Security_Deserialize_KeyMaterial_AES_GCM_GMAC(deserializer, &remote_key_mat))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else if (!check_crypto_keymaterial(&remote_key_mat))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0,
"set_remote_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE);
result = false;
}
else
{
factory = cryptography_get_crypto_key_factory(impl->crypto);
result = crypto_factory_set_datareader_crypto_tokens(factory, local_writer_handle, remote_reader_handle, &remote_key_mat, ex);
}
DDS_Security_KeyMaterial_AES_GCM_GMAC_deinit(&remote_key_mat);
DDS_Security_Deserializer_free(deserializer);
return result;
}
static DDS_Security_boolean
return_crypto_tokens(
dds_security_crypto_key_exchange *instance,
DDS_Security_CryptoTokenSeq *tokens,
DDS_Security_SecurityException *ex)
{
dds_security_crypto_key_exchange_impl *impl = (dds_security_crypto_key_exchange_impl *)instance;
if (!impl || !tokens)
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"return_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
goto fail_invalid_arg;
}
if (!check_crypto_tokens(tokens))
{
DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0,
"set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE);
goto fail_invalid_arg;
}
DDS_Security_CryptoTokenSeq_freebuf(tokens);
memset(tokens, 0, sizeof(*tokens));
return true;
fail_invalid_arg:
return false;
}
dds_security_crypto_key_exchange *
dds_security_crypto_key_exchange__alloc(
const dds_security_cryptography *crypto)
{
dds_security_crypto_key_exchange_impl *instance = ddsrt_malloc(sizeof(*instance));
instance->crypto = crypto;
instance->base.create_local_participant_crypto_tokens = &create_local_participant_crypto_tokens;
instance->base.set_remote_participant_crypto_tokens = &set_remote_participant_crypto_tokens;
instance->base.create_local_datawriter_crypto_tokens = &create_local_datawriter_crypto_tokens;
instance->base.set_remote_datawriter_crypto_tokens = &set_remote_datawriter_crypto_tokens;
instance->base.create_local_datareader_crypto_tokens = &create_local_datareader_crypto_tokens;
instance->base.set_remote_datareader_crypto_tokens = &set_remote_datareader_crypto_tokens;
instance->base.return_crypto_tokens = &return_crypto_tokens;
return (dds_security_crypto_key_exchange *)instance;
}
void dds_security_crypto_key_exchange__dealloc(
dds_security_crypto_key_exchange *instance)
{
ddsrt_free(instance);
}

View file

@ -0,0 +1,27 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTO_KEY_EXCHANGE_H
#define CRYPTO_KEY_EXCHANGE_H
#include "dds/security/dds_security_api.h"
/**
* @brief Allocation function for implementer structure (with internal variables) transparently.
*/
dds_security_crypto_key_exchange *
dds_security_crypto_key_exchange__alloc(
const dds_security_cryptography *crypto);
void dds_security_crypto_key_exchange__dealloc(
dds_security_crypto_key_exchange *instance);
#endif /* CRYPTO_KEY_EXCHANGE_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,146 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTO_KEY_FACTORY_H
#define CRYPTO_KEY_FACTORY_H
#include "dds/security/dds_security_api.h"
#include "crypto_objects.h"
/**
* @brief Allocation function for implementer structure (with internal variables) transparently.
*/
dds_security_crypto_key_factory *
dds_security_crypto_key_factory__alloc(
const dds_security_cryptography *crypto);
void dds_security_crypto_key_factory__dealloc(
dds_security_crypto_key_factory *instance);
int generate_key_pairs(
char **private_key,
char **public_key);
bool crypto_factory_get_participant_crypto_tokens(
const dds_security_crypto_key_factory *factory,
DDS_Security_ParticipantCryptoHandle local_id,
DDS_Security_ParticipantCryptoHandle remote_id,
participant_key_material **pp_key_material,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_set_participant_crypto_tokens(
const dds_security_crypto_key_factory *factory,
const DDS_Security_ParticipantCryptoHandle local_id,
const DDS_Security_ParticipantCryptoHandle remote_id,
const DDS_Security_KeyMaterial_AES_GCM_GMAC *remote_key_mat,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_datawriter_crypto_tokens(
const dds_security_crypto_key_factory *factory,
DDS_Security_DatawriterCryptoHandle local_writer_handle,
DDS_Security_DatareaderCryptoHandle remote_reader_handle,
master_key_material **key_mat,
uint32_t *num_key_mat,
DDS_Security_SecurityException *ex);
bool crypto_factory_set_datawriter_crypto_tokens(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatawriterCryptoHandle local_reader_handle,
const DDS_Security_DatareaderCryptoHandle remote_writer_handle,
const DDS_Security_KeyMaterial_AES_GCM_GMAC *key_mat,
const uint32_t num_key_mat,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_datareader_crypto_tokens(
const dds_security_crypto_key_factory *factory,
DDS_Security_DatawriterCryptoHandle local_reader_handle,
DDS_Security_DatareaderCryptoHandle remote_writer_handle,
master_key_material **key_mat,
DDS_Security_SecurityException *ex);
bool crypto_factory_set_datareader_crypto_tokens(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatawriterCryptoHandle local_writer_handle,
const DDS_Security_DatareaderCryptoHandle remote_reader_handle,
const DDS_Security_KeyMaterial_AES_GCM_GMAC *key_mat,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_writer_key_material(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatawriterCryptoHandle writer_id,
const DDS_Security_DatareaderCryptoHandle reader_id,
bool payload,
session_key_material **session_key,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_reader_key_material(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatareaderCryptoHandle reader_id,
const DDS_Security_DatawriterCryptoHandle writer_id,
session_key_material **session_key,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_remote_writer_key_material(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatareaderCryptoHandle reader_id,
const DDS_Security_DatawriterCryptoHandle writer_id,
uint32_t key_id,
master_key_material **master_key,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_BasicProtectionKind *basic_protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_local_participant_data_key_material(
const dds_security_crypto_key_factory *factory,
const DDS_Security_ParticipantCryptoHandle local_id,
session_key_material **session_key,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_remote_reader_key_material(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatawriterCryptoHandle writer_id,
const DDS_Security_DatareaderCryptoHandle reader_id,
uint32_t key_id,
master_key_material **master_key,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_remote_writer_sign_key_material(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatareaderCryptoHandle writer_id,
master_key_material **key_material,
session_key_material **session_key,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_remote_reader_sign_key_material(
const dds_security_crypto_key_factory *factory,
const DDS_Security_DatareaderCryptoHandle reader_id,
master_key_material **key_material,
session_key_material **session_key,
DDS_Security_ProtectionKind *protection_kind,
DDS_Security_SecurityException *ex);
bool crypto_factory_get_endpoint_relation(
const dds_security_crypto_key_factory *factory,
DDS_Security_ParticipantCryptoHandle local_participant_handle,
DDS_Security_ParticipantCryptoHandle remote_participant_handle,
uint32_t key_id,
DDS_Security_Handle *remote_handle,
DDS_Security_Handle *local_handle,
DDS_Security_SecureSubmessageCategory_t *category,
DDS_Security_SecurityException *ex);
#endif /* CRYPTO_KEY_FACTORY_H */

View file

@ -0,0 +1,593 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/hopscotch.h"
#include "dds/ddsrt/types.h"
#include "crypto_objects.h"
#include "crypto_utils.h"
bool crypto_object_valid(CryptoObject *obj, CryptoObjectKind_t kind)
{
return (obj && obj->kind == kind && obj->handle == (int64_t)(uintptr_t)obj);
}
static uint32_t crypto_object_hash(const void *obj)
{
const CryptoObject *object = obj;
const uint64_t c = UINT64_C (16292676669999574021);
const uint32_t x = (uint32_t)object->handle;
return (uint32_t)((x * c) >> 32);
}
static int crypto_object_equal(const void *ha, const void *hb)
{
const CryptoObject *la = ha;
const CryptoObject *lb = hb;
return la->handle == lb->handle;
}
void crypto_object_init(CryptoObject *obj, CryptoObjectKind_t kind, CryptoObjectDestructor destructor)
{
assert(obj);
obj->kind = kind;
obj->handle = (int64_t)(uintptr_t)obj;
obj->destructor = destructor;
ddsrt_atomic_st32 (&obj->refcount, 1);
}
static void crypto_object_deinit(CryptoObject *obj)
{
assert(obj);
obj->handle = DDS_SECURITY_HANDLE_NIL;
obj->kind = CRYPTO_OBJECT_KIND_UNKNOWN;
obj->destructor = NULL;
}
void crypto_object_free(CryptoObject *obj)
{
if (obj && obj->destructor)
obj->destructor(obj);
}
CryptoObject * crypto_object_keep(CryptoObject *obj)
{
if (obj)
ddsrt_atomic_inc32(&obj->refcount);
return obj;
}
void crypto_object_release(CryptoObject *obj)
{
if (obj && ddsrt_atomic_dec32_nv(&obj->refcount) == 0)
crypto_object_free(obj);
}
static uint32_t participant_key_material_hash(const void *obj)
{
const participant_key_material *object = obj;
return (uint32_t)object->pp_local_handle;
}
static int participant_key_material_equal(const void *ha, const void *hb)
{
const participant_key_material *la = ha;
const participant_key_material *lb = hb;
return la->pp_local_handle == lb->pp_local_handle;
}
static CryptoObject * participant_key_material_find(const struct CryptoObjectTable *table, const void *arg)
{
struct participant_key_material template;
template.pp_local_handle = *(int64_t *)arg;
return crypto_object_table_find_by_template(table, &template);
}
CryptoObject * crypto_object_table_find_by_template(const struct CryptoObjectTable *table, const void *template)
{
return (CryptoObject *)ddsrt_hh_lookup(table->htab, template);
}
static CryptoObject * default_crypto_table_find(const struct CryptoObjectTable *table, const void *arg)
{
struct CryptoObject template;
template.handle = *(int64_t *)arg;
return crypto_object_table_find_by_template(table, &template);
}
struct CryptoObjectTable * crypto_object_table_new(CryptoObjectHashFunction hashfnc, CryptoObjectEqualFunction equalfnc, CryptoObjectFindFunction findfnc)
{
struct CryptoObjectTable *table;
if (!hashfnc)
hashfnc = crypto_object_hash;
if (!equalfnc)
equalfnc = crypto_object_equal;
table = ddsrt_malloc(sizeof(*table));
table->htab = ddsrt_hh_new(32, hashfnc, equalfnc);
ddsrt_mutex_init(&table->lock);
table->findfnc = findfnc ? findfnc : default_crypto_table_find;
return table;
}
void crypto_object_table_free(struct CryptoObjectTable *table)
{
struct ddsrt_hh_iter it;
CryptoObject *obj;
if (!table)
return;
ddsrt_mutex_lock(&table->lock);
for (obj = ddsrt_hh_iter_first(table->htab, &it); obj; obj = ddsrt_hh_iter_next(&it))
{
ddsrt_hh_remove(table->htab, obj);
crypto_object_release(obj);
}
ddsrt_hh_free(table->htab);
ddsrt_mutex_unlock(&table->lock);
ddsrt_mutex_destroy(&table->lock);
ddsrt_free(table);
}
CryptoObject * crypto_object_table_insert(struct CryptoObjectTable *table, CryptoObject *object)
{
CryptoObject *cur;
assert(table);
assert(object);
ddsrt_mutex_lock(&table->lock);
if (!(cur = crypto_object_keep (table->findfnc(table, &object->handle))))
ddsrt_hh_add(table->htab, crypto_object_keep(object));
else
crypto_object_release(cur);
ddsrt_mutex_unlock(&table->lock);
return cur;
}
void crypto_object_table_remove_object(struct CryptoObjectTable *table, CryptoObject *object)
{
assert (table);
assert (object);
ddsrt_mutex_lock (&table->lock);
ddsrt_hh_remove (table->htab, object);
ddsrt_mutex_unlock (&table->lock);
crypto_object_release (object);
}
CryptoObject * crypto_object_table_remove(struct CryptoObjectTable *table, int64_t handle)
{
CryptoObject *object;
assert (table);
ddsrt_mutex_lock (&table->lock);
if ((object = crypto_object_keep (table->findfnc(table, &handle))))
{
ddsrt_hh_remove (table->htab, object);
crypto_object_release (object);
}
ddsrt_mutex_unlock (&table->lock);
return object;
}
CryptoObject * crypto_object_table_find(struct CryptoObjectTable *table, int64_t handle)
{
CryptoObject *object;
assert (table);
ddsrt_mutex_lock (&table->lock);
object = crypto_object_keep (table->findfnc(table, &handle));
ddsrt_mutex_unlock (&table->lock);
return object;
}
void crypto_object_table_walk(struct CryptoObjectTable *table, CryptoObjectTableCallback callback, void *arg)
{
struct ddsrt_hh_iter it;
CryptoObject *obj;
int r = 1;
assert(table);
assert(callback);
ddsrt_mutex_lock (&table->lock);
for (obj = ddsrt_hh_iter_first (table->htab, &it); r && obj; obj = ddsrt_hh_iter_next (&it))
r = callback(obj, arg);
ddsrt_mutex_unlock(&table->lock);
}
static void master_key_material__free(CryptoObject *obj)
{
master_key_material *keymat = (master_key_material *)obj;
if (obj)
{
CHECK_CRYPTO_OBJECT_KIND(obj, CRYPTO_OBJECT_KIND_KEY_MATERIAL);
if (CRYPTO_TRANSFORM_HAS_KEYS(keymat->transformation_kind))
{
ddsrt_free (keymat->master_salt);
ddsrt_free (keymat->master_sender_key);
ddsrt_free (keymat->master_receiver_specific_key);
}
crypto_object_deinit ((CryptoObject *)keymat);
memset (keymat, 0, sizeof (*keymat));
ddsrt_free (keymat);
}
}
master_key_material * crypto_master_key_material_new(DDS_Security_CryptoTransformKind_Enum transform_kind)
{
master_key_material *keymat = ddsrt_calloc (1, sizeof(*keymat));
crypto_object_init((CryptoObject *)keymat, CRYPTO_OBJECT_KIND_KEY_MATERIAL, master_key_material__free);
keymat->transformation_kind = transform_kind;
if (CRYPTO_TRANSFORM_HAS_KEYS(transform_kind))
{
uint32_t key_bytes = CRYPTO_KEY_SIZE_BYTES(keymat->transformation_kind);
keymat->master_salt = ddsrt_calloc(1, key_bytes);
keymat->master_sender_key = ddsrt_calloc(1, key_bytes);
keymat->master_receiver_specific_key = ddsrt_calloc(1, key_bytes);
}
return keymat;
}
void crypto_master_key_material_set(master_key_material *dst, const master_key_material *src)
{
if (CRYPTO_TRANSFORM_HAS_KEYS(dst->transformation_kind) && !CRYPTO_TRANSFORM_HAS_KEYS(src->transformation_kind))
{
ddsrt_free(dst->master_salt);
ddsrt_free(dst->master_sender_key);
ddsrt_free(dst->master_receiver_specific_key);
}
else if (CRYPTO_TRANSFORM_HAS_KEYS(src->transformation_kind))
{
uint32_t key_bytes = CRYPTO_KEY_SIZE_BYTES(src->transformation_kind);
if (!CRYPTO_TRANSFORM_HAS_KEYS(dst->transformation_kind))
{
dst->master_salt = ddsrt_calloc(1, key_bytes);
dst->master_sender_key = ddsrt_calloc(1, key_bytes);
dst->master_receiver_specific_key = ddsrt_calloc(1, key_bytes);
}
memcpy (dst->master_salt, src->master_salt, key_bytes);
dst->sender_key_id = src->sender_key_id;
memcpy (dst->master_sender_key, src->master_sender_key, key_bytes);
/* Fixme: set the receiver specific key? */
dst->receiver_specific_key_id = 0;
}
dst->transformation_kind = src->transformation_kind;
}
static bool generate_session_key(session_key_material *session, DDS_Security_SecurityException *ex)
{
session->id++;
session->block_counter = 0;
return crypto_calculate_session_key(&session->key, session->id, session->master_key_material->master_salt, session->master_key_material->master_sender_key, session->master_key_material->transformation_kind, ex);
}
static void session_key_material__free(CryptoObject *obj)
{
session_key_material *session = (session_key_material *)obj;
if (obj)
{
CHECK_CRYPTO_OBJECT_KIND(obj, CRYPTO_OBJECT_KIND_SESSION_KEY_MATERIAL);
CRYPTO_OBJECT_RELEASE(session->master_key_material);
crypto_object_deinit((CryptoObject *)session);
memset (session, 0, sizeof (*session));
ddsrt_free(session);
}
}
session_key_material * crypto_session_key_material_new(master_key_material *master_key)
{
session_key_material *session = ddsrt_malloc(sizeof(*session));
crypto_object_init((CryptoObject *)session, CRYPTO_OBJECT_KIND_SESSION_KEY_MATERIAL, session_key_material__free);
memset (session->key.data, 0, CRYPTO_KEY_SIZE_MAX);
session->block_size = CRYPTO_CIPHER_BLOCK_SIZE;
session->key_size = crypto_get_key_size(master_key->transformation_kind);
session->id = crypto_get_random_uint32();
session->init_vector_suffix = crypto_get_random_uint64();
session->max_blocks_per_session = INT64_MAX; /* FIXME: should be a config parameter */
session->block_counter = session->max_blocks_per_session;
session->master_key_material = (master_key_material *)CRYPTO_OBJECT_KEEP(master_key);
return session;
}
bool crypto_session_key_material_update(session_key_material *session, uint32_t size, DDS_Security_SecurityException *ex)
{
if (session->block_counter + (size / session->block_size) >= session->max_blocks_per_session)
return generate_session_key(session, ex);
return true;
}
static void local_participant_crypto__free(CryptoObject *obj)
{
local_participant_crypto *participant_crypto = (local_participant_crypto *)obj;
if (participant_crypto)
{
CHECK_CRYPTO_OBJECT_KIND (obj, CRYPTO_OBJECT_KIND_LOCAL_CRYPTO);
CRYPTO_OBJECT_RELEASE (participant_crypto->session);
CRYPTO_OBJECT_RELEASE (participant_crypto->key_material);
crypto_object_deinit ((CryptoObject *)participant_crypto);
ddsrt_free (participant_crypto);
}
}
local_participant_crypto * crypto_local_participant_crypto__new(DDS_Security_IdentityHandle participant_identity)
{
assert (participant_identity);
assert (sizeof(DDS_Security_ParticipantCryptoHandle) == 8);
local_participant_crypto *participant_crypto = ddsrt_calloc (1, sizeof(*participant_crypto));
participant_crypto->identity_handle = participant_identity;
crypto_object_init ((CryptoObject *)participant_crypto, CRYPTO_OBJECT_KIND_LOCAL_CRYPTO, local_participant_crypto__free);
return participant_crypto;
}
static void remote_participant_crypto__free(CryptoObject *obj)
{
remote_participant_crypto *participant_crypto = (remote_participant_crypto *)obj;
CHECK_CRYPTO_OBJECT_KIND (obj, CRYPTO_OBJECT_KIND_REMOTE_CRYPTO);
if (participant_crypto)
{
CRYPTO_OBJECT_RELEASE (participant_crypto->session);
crypto_object_table_free (participant_crypto->key_material);
crypto_object_deinit ((CryptoObject *)participant_crypto);
ddsrt_free(participant_crypto);
}
}
remote_participant_crypto * crypto_remote_participant_crypto__new(DDS_Security_IdentityHandle participant_identity)
{
assert (participant_identity);
remote_participant_crypto *participant_crypto = ddsrt_calloc (1, sizeof(*participant_crypto));
crypto_object_init ((CryptoObject *)participant_crypto, CRYPTO_OBJECT_KIND_REMOTE_CRYPTO, remote_participant_crypto__free);
participant_crypto->identity_handle = participant_identity;
participant_crypto->key_material = crypto_object_table_new (participant_key_material_hash, participant_key_material_equal, participant_key_material_find);
return participant_crypto;
}
static void participant_key_material_free(CryptoObject *obj)
{
participant_key_material *keymaterial = (participant_key_material *)obj;
CHECK_CRYPTO_OBJECT_KIND(obj, CRYPTO_OBJECT_KIND_PARTICIPANT_KEY_MATERIAL);
if (keymaterial)
{
CRYPTO_OBJECT_RELEASE(keymaterial->P2P_writer_session);
CRYPTO_OBJECT_RELEASE(keymaterial->P2P_reader_session);
CRYPTO_OBJECT_RELEASE(keymaterial->P2P_kx_key_material);
CRYPTO_OBJECT_RELEASE(keymaterial->local_P2P_key_material);
CRYPTO_OBJECT_RELEASE(keymaterial->remote_key_material);
crypto_object_table_free(keymaterial->endpoint_relations);
crypto_object_deinit((CryptoObject *)keymaterial);
ddsrt_free(keymaterial);
}
}
participant_key_material * crypto_participant_key_material_new(const local_participant_crypto *pplocal)
{
participant_key_material *keymaterial = ddsrt_calloc(1, sizeof(*keymaterial));
crypto_object_init((CryptoObject *)keymaterial, CRYPTO_OBJECT_KIND_PARTICIPANT_KEY_MATERIAL, participant_key_material_free);
keymaterial->pp_local_handle = pplocal->_parent.handle;
keymaterial->endpoint_relations = crypto_object_table_new(NULL, NULL, NULL);
keymaterial->local_P2P_key_material = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_NONE);
keymaterial->P2P_kx_key_material = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_AES256_GCM); /* as defined in table 67 of the DDS Security spec v1.1 */
return keymaterial;
}
static void endpoint_relation_free(CryptoObject *obj)
{
endpoint_relation *relation = (endpoint_relation *)obj;
if (relation)
{
CRYPTO_OBJECT_RELEASE(relation->local_crypto);
CRYPTO_OBJECT_RELEASE(relation->remote_crypto);
crypto_object_deinit((CryptoObject *)relation);
ddsrt_free(relation);
}
}
endpoint_relation * crypto_endpoint_relation_new(DDS_Security_SecureSubmessageCategory_t kind,
uint32_t key_id, CryptoObject *local_crypto, CryptoObject *remote_crypto)
{
endpoint_relation *relation = ddsrt_malloc(sizeof(*relation));
crypto_object_init((CryptoObject *)relation, CRYPTO_OBJECT_KIND_ENDPOINT_RELATION, endpoint_relation_free);
relation->kind = kind;
relation->key_id = key_id;
relation->local_crypto = CRYPTO_OBJECT_KEEP(local_crypto);
relation->remote_crypto = CRYPTO_OBJECT_KEEP(remote_crypto);
return relation;
}
static void local_datawriter_crypto__free(CryptoObject *obj)
{
local_datawriter_crypto *datawriter_crypto = (local_datawriter_crypto *)obj;
if (obj)
{
CHECK_CRYPTO_OBJECT_KIND(obj, CRYPTO_OBJECT_KIND_LOCAL_WRITER_CRYPTO);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer_session_message);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer_session_payload);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer_key_material_message);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer_key_material_payload);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->participant);
crypto_object_deinit((CryptoObject *)datawriter_crypto);
ddsrt_free(datawriter_crypto);
}
}
local_datawriter_crypto * crypto_local_datawriter_crypto__new(const local_participant_crypto *participant,
DDS_Security_ProtectionKind meta_protection, DDS_Security_BasicProtectionKind data_protection)
{
local_datawriter_crypto *writer_crypto = ddsrt_calloc(1, sizeof(*writer_crypto));
crypto_object_init((CryptoObject *)writer_crypto, CRYPTO_OBJECT_KIND_LOCAL_WRITER_CRYPTO, local_datawriter_crypto__free);
writer_crypto->participant = (local_participant_crypto *)CRYPTO_OBJECT_KEEP(participant);
writer_crypto->metadata_protectionKind = meta_protection;
writer_crypto->data_protectionKind = data_protection;
writer_crypto->is_builtin_participant_volatile_message_secure_writer = false;
return writer_crypto;
}
static void remote_datawriter_crypto__free(CryptoObject *obj)
{
remote_datawriter_crypto *datawriter_crypto = (remote_datawriter_crypto *)obj;
if (datawriter_crypto)
{
CHECK_CRYPTO_OBJECT_KIND(obj, CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->reader_session);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->reader2writer_key_material);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer2reader_key_material[0]);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer2reader_key_material[1]);
CRYPTO_OBJECT_RELEASE(datawriter_crypto->participant);
crypto_object_deinit((CryptoObject *)datawriter_crypto);
ddsrt_free(datawriter_crypto);
}
}
remote_datawriter_crypto * crypto_remote_datawriter_crypto__new(const remote_participant_crypto *participant,
DDS_Security_ProtectionKind meta_protection, DDS_Security_BasicProtectionKind data_protection, DDS_Security_DatareaderCryptoHandle local_reader_handle)
{
remote_datawriter_crypto *writer_crypto = ddsrt_calloc(1, sizeof(*writer_crypto));
crypto_object_init((CryptoObject *)writer_crypto, CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO, remote_datawriter_crypto__free);
writer_crypto->participant = (remote_participant_crypto *)CRYPTO_OBJECT_KEEP(participant);
writer_crypto->metadata_protectionKind = meta_protection;
writer_crypto->data_protectionKind = data_protection;
writer_crypto->local_reader_handle = local_reader_handle;
writer_crypto->is_builtin_participant_volatile_message_secure_writer = false;
return writer_crypto;
}
static void local_datareader_crypto__free(CryptoObject *obj)
{
local_datareader_crypto *datareader_crypto = (local_datareader_crypto *)obj;
if (datareader_crypto)
{
CHECK_CRYPTO_OBJECT_KIND(obj, CRYPTO_OBJECT_KIND_LOCAL_READER_CRYPTO);
CRYPTO_OBJECT_RELEASE(datareader_crypto->reader_session);
CRYPTO_OBJECT_RELEASE(datareader_crypto->reader_key_material);
CRYPTO_OBJECT_RELEASE(datareader_crypto->participant);
crypto_object_deinit((CryptoObject *)datareader_crypto);
ddsrt_free(datareader_crypto);
}
}
local_datareader_crypto * crypto_local_datareader_crypto__new(const local_participant_crypto *participant,
DDS_Security_ProtectionKind meta_protection, DDS_Security_BasicProtectionKind data_protection)
{
local_datareader_crypto *reader_crypto = ddsrt_calloc(1, sizeof(*reader_crypto));
crypto_object_init((CryptoObject *)reader_crypto, CRYPTO_OBJECT_KIND_LOCAL_READER_CRYPTO, local_datareader_crypto__free);
reader_crypto->participant = (local_participant_crypto *)CRYPTO_OBJECT_KEEP(participant);
reader_crypto->metadata_protectionKind = meta_protection;
reader_crypto->data_protectionKind = data_protection;
reader_crypto->is_builtin_participant_volatile_message_secure_reader = false;
return reader_crypto;
}
static void remote_datareader_crypto__free(CryptoObject *obj)
{
remote_datareader_crypto *datareader_crypto = (remote_datareader_crypto *)obj;
if (datareader_crypto)
{
CHECK_CRYPTO_OBJECT_KIND(obj, CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO);
CRYPTO_OBJECT_RELEASE(datareader_crypto->writer_session);
CRYPTO_OBJECT_RELEASE(datareader_crypto->reader2writer_key_material);
CRYPTO_OBJECT_RELEASE(datareader_crypto->writer2reader_key_material_message);
CRYPTO_OBJECT_RELEASE(datareader_crypto->writer2reader_key_material_payload);
CRYPTO_OBJECT_RELEASE(datareader_crypto->participant);
crypto_object_deinit((CryptoObject *)datareader_crypto);
ddsrt_free(datareader_crypto);
}
}
remote_datareader_crypto *crypto_remote_datareader_crypto__new(const remote_participant_crypto *participant, DDS_Security_ProtectionKind metadata_protectionKind,
DDS_Security_BasicProtectionKind data_protectionKind, DDS_Security_DatawriterCryptoHandle local_writer_handle)
{
remote_datareader_crypto *reader_crypto = ddsrt_calloc(1, sizeof(*reader_crypto));
crypto_object_init((CryptoObject *)reader_crypto, CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO, remote_datareader_crypto__free);
reader_crypto->participant = (remote_participant_crypto *)CRYPTO_OBJECT_KEEP(participant);
reader_crypto->metadata_protectionKind = metadata_protectionKind;
reader_crypto->data_protectionKind = data_protectionKind;
reader_crypto->local_writer_handle = local_writer_handle;
reader_crypto->is_builtin_participant_volatile_message_secure_reader = false;
return reader_crypto;
}
typedef struct endpoint_relation_find_arg
{
CryptoObject *found;
CryptoObject *local_crypto;
CryptoObject *remote_crypto;
uint32_t key_id;
} endpoint_relation_find_arg;
static int endpoint_relation_cmp_key(CryptoObject *obj, void *arg)
{
const endpoint_relation *rel = (const endpoint_relation *)obj;
endpoint_relation_find_arg *find_arg = (endpoint_relation_find_arg *)arg;
if (rel->key_id == find_arg->key_id)
{
find_arg->found = crypto_object_keep(obj);
return 0;
}
return 1;
}
static int endpoint_relation_cmp_crypto(CryptoObject *obj, void *arg)
{
const endpoint_relation *rel = (const endpoint_relation *)obj;
endpoint_relation_find_arg *find_arg = (endpoint_relation_find_arg *)arg;
if ((rel->local_crypto == find_arg->local_crypto) &&
(rel->remote_crypto == find_arg->remote_crypto))
{
find_arg->found = crypto_object_keep(obj);
return 0;
}
return 1;
}
endpoint_relation * crypto_endpoint_relation_find_by_key(struct CryptoObjectTable *table, uint32_t key_id)
{
endpoint_relation_find_arg find_arg;
find_arg.found = NULL;
find_arg.key_id = key_id;
find_arg.local_crypto = NULL;
find_arg.remote_crypto = NULL;
crypto_object_table_walk(table, endpoint_relation_cmp_key, &find_arg);
return (endpoint_relation *)(find_arg.found);
}
endpoint_relation * crypto_endpoint_relation_find_by_crypto(struct CryptoObjectTable *table, CryptoObject *local_crypto, CryptoObject *remote_crypto)
{
endpoint_relation_find_arg find_arg;
find_arg.found = NULL;
find_arg.key_id = 0;
find_arg.local_crypto = local_crypto;
find_arg.remote_crypto = remote_crypto;
crypto_object_table_walk(table, endpoint_relation_cmp_crypto, &find_arg);
return (endpoint_relation *)(find_arg.found);
}

View file

@ -0,0 +1,354 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTO_OBJECTS_H
#define CRYPTO_OBJECTS_H
#include <openssl/rand.h>
#include "dds/ddsrt/atomics.h"
#include "dds/ddsrt/sync.h"
#include "dds/ddsrt/types.h"
#include "dds/security/dds_security_api.h"
#include "dds/security/core/dds_security_utils.h"
#include "crypto_defs.h"
#ifndef NDEBUG
#define CHECK_CRYPTO_OBJECT_KIND(o, k) assert(crypto_object_valid((CryptoObject *)(o), k))
#else
#define CHECK_CRYPTO_OBJECT_KIND(o, k)
#endif
#define CRYPTO_OBJECT(o) ((CryptoObject *)(o))
#define CRYPTO_OBJECT_HANDLE(o) (CRYPTO_OBJECT(o)->handle)
#define PARTICIPANT_CRYPTO_HANDLE(o) ((DDS_Security_ParticipantCryptoHandle)CRYPTO_OBJECT_HANDLE(o))
#define DATAWRITER_CRYPTO_HANDLE(o) ((DDS_Security_DatawriterCryptoHandle)CRYPTO_OBJECT_HANDLE(o))
#define DATAREADER_CRYPTO_HANDLE(o) ((DDS_Security_DatareaderCryptoHandle)CRYPTO_OBJECT_HANDLE(o))
#define CRYPTO_OBJECT_KEEP(o) crypto_object_keep((CryptoObject *)(o))
#define CRYPTO_OBJECT_RELEASE(o) crypto_object_release((CryptoObject *)(o))
#define CRYPTO_OBJECT_VALID(o, k) crypto_object_valid((CryptoObject *)(o), k)
#define CRYPTO_TRANSFORM_HAS_KEYS(k) ((k) != CRYPTO_TRANSFORMATION_KIND_NONE && (k) != CRYPTO_TRANSFORMATION_KIND_INVALID)
typedef DDS_Security_ParticipantCryptoHandle DDS_Security_LocalParticipantCryptoHandle;
typedef DDS_Security_ParticipantCryptoHandle DDS_Security_RemoteParticipantCryptoHandle;
typedef enum
{
CRYPTO_OBJECT_KIND_UNKNOWN,
CRYPTO_OBJECT_KIND_LOCAL_CRYPTO,
CRYPTO_OBJECT_KIND_REMOTE_CRYPTO,
CRYPTO_OBJECT_KIND_LOCAL_WRITER_CRYPTO,
CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO,
CRYPTO_OBJECT_KIND_LOCAL_READER_CRYPTO,
CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO,
CRYPTO_OBJECT_KIND_KEY_MATERIAL,
CRYPTO_OBJECT_KIND_SESSION_KEY_MATERIAL,
CRYPTO_OBJECT_KIND_PARTICIPANT_KEY_MATERIAL,
CRYPTO_OBJECT_KIND_ENDPOINT_RELATION
} CryptoObjectKind_t;
typedef struct CryptoObject CryptoObject;
typedef void (*CryptoObjectDestructor)(CryptoObject *obj);
struct CryptoObject
{
int64_t handle;
ddsrt_atomic_uint32_t refcount;
CryptoObjectKind_t kind;
CryptoObjectDestructor destructor;
};
struct local_datawriter_crypto;
struct local_datareader_crypto;
struct remote_datawriter_crypto;
struct remote_datareader_crypto;
typedef struct master_key_material
{
CryptoObject _parent;
DDS_Security_CryptoTransformKind_Enum transformation_kind;
unsigned char *master_salt;
uint32_t sender_key_id;
unsigned char *master_sender_key;
uint32_t receiver_specific_key_id;
unsigned char *master_receiver_specific_key;
} master_key_material;
typedef struct session_key_material
{
CryptoObject _parent;
uint32_t id;
crypto_session_key_t key;
uint32_t key_size;
uint32_t block_size;
uint64_t block_counter;
uint64_t max_blocks_per_session;
uint64_t init_vector_suffix;
master_key_material *master_key_material;
} session_key_material;
typedef struct remote_session_info
{
uint32_t key_size;
uint32_t id;
crypto_session_key_t key;
} remote_session_info;
typedef struct endpoint_relation
{
CryptoObject _parent;
DDS_Security_SecureSubmessageCategory_t kind;
uint32_t key_id;
CryptoObject *local_crypto;
CryptoObject *remote_crypto;
} endpoint_relation;
typedef struct local_participant_crypto
{
CryptoObject _parent;
master_key_material *key_material;
DDS_Security_IdentityHandle identity_handle;
session_key_material *session;
DDS_Security_ProtectionKind rtps_protection_kind;
} local_participant_crypto;
typedef struct participant_key_material
{
CryptoObject _parent;
DDS_Security_ParticipantCryptoHandle pp_local_handle;
master_key_material *remote_key_material;
master_key_material *local_P2P_key_material;
master_key_material *P2P_kx_key_material;
session_key_material *P2P_writer_session;
session_key_material *P2P_reader_session;
struct CryptoObjectTable *endpoint_relations;
} participant_key_material;
typedef struct remote_participant_crypto
{
CryptoObject _parent;
DDS_Security_GUID_t remoteGuid;
DDS_Security_IdentityHandle identity_handle;
struct CryptoObjectTable *key_material;
session_key_material *session;
DDS_Security_ProtectionKind rtps_protection_kind;
} remote_participant_crypto;
typedef struct local_datawriter_crypto
{
CryptoObject _parent;
local_participant_crypto *participant;
master_key_material *writer_key_material_message;
master_key_material *writer_key_material_payload;
session_key_material *writer_session_message;
session_key_material *writer_session_payload;
DDS_Security_ProtectionKind metadata_protectionKind;
DDS_Security_BasicProtectionKind data_protectionKind;
bool is_builtin_participant_volatile_message_secure_writer;
} local_datawriter_crypto;
typedef struct remote_datawriter_crypto
{
CryptoObject _parent;
remote_participant_crypto *participant;
DDS_Security_ProtectionKind metadata_protectionKind;
DDS_Security_BasicProtectionKind data_protectionKind;
master_key_material *reader2writer_key_material;
master_key_material *writer2reader_key_material[2];
session_key_material *reader_session; /* reference to the session key used by the reader */
DDS_Security_DatareaderCryptoHandle local_reader_handle;
bool is_builtin_participant_volatile_message_secure_writer;
} remote_datawriter_crypto;
typedef struct local_datareader_crypto
{
CryptoObject _parent;
local_participant_crypto *participant;
master_key_material *reader_key_material;
session_key_material *reader_session;
DDS_Security_ProtectionKind metadata_protectionKind;
DDS_Security_BasicProtectionKind data_protectionKind;
bool is_builtin_participant_volatile_message_secure_reader;
} local_datareader_crypto;
typedef struct remote_datareader_crypto
{
CryptoObject _parent;
remote_participant_crypto *participant;
DDS_Security_ProtectionKind metadata_protectionKind;
DDS_Security_BasicProtectionKind data_protectionKind;
master_key_material *reader2writer_key_material;
master_key_material *writer2reader_key_material_message;
master_key_material *writer2reader_key_material_payload;
session_key_material *writer_session; /* reference to the session key used by the writer */
DDS_Security_DatawriterCryptoHandle local_writer_handle;
bool is_builtin_participant_volatile_message_secure_reader;
} remote_datareader_crypto;
master_key_material *
crypto_master_key_material_new(DDS_Security_CryptoTransformKind_Enum transform_kind);
void crypto_master_key_material_set(
master_key_material *dst,
const master_key_material *src);
session_key_material *
crypto_session_key_material_new(
master_key_material *master_key);
bool crypto_session_key_material_update(
session_key_material *session,
uint32_t size,
DDS_Security_SecurityException *ex);
local_participant_crypto *
crypto_local_participant_crypto__new(
DDS_Security_IdentityHandle participant_identity);
remote_participant_crypto *
crypto_remote_participant_crypto__new(
DDS_Security_IdentityHandle participant_identity);
void crypto_object_init(
CryptoObject *obj,
CryptoObjectKind_t kind,
CryptoObjectDestructor destructor);
endpoint_relation *
crypto_endpoint_relation_new(
DDS_Security_SecureSubmessageCategory_t kind,
uint32_t key_id,
CryptoObject *local_crypto,
CryptoObject *remote_crypto);
endpoint_relation *
crypto_endpoint_relation_find_by_key(
struct CryptoObjectTable *table,
uint32_t key_id);
endpoint_relation *
crypto_endpoint_relation_find_by_crypto(
struct CryptoObjectTable *table,
CryptoObject *local_crypto,
CryptoObject *remote_crypto);
bool endpoint_relation_get_locals(
const endpoint_relation *relation,
const local_participant_crypto *participant,
DDS_Security_HandleSeq *list);
local_datawriter_crypto *
crypto_local_datawriter_crypto__new(
const local_participant_crypto *participant,
DDS_Security_ProtectionKind meta_protection,
DDS_Security_BasicProtectionKind data_protection);
remote_datareader_crypto *
crypto_remote_datareader_crypto__new(
const remote_participant_crypto *participant,
DDS_Security_ProtectionKind metadata_protectionKind,
DDS_Security_BasicProtectionKind data_protectionKind,
DDS_Security_DatawriterCryptoHandle local_writer_handle);
local_datareader_crypto *
crypto_local_datareader_crypto__new(
const local_participant_crypto *participant,
DDS_Security_ProtectionKind meta_protection,
DDS_Security_BasicProtectionKind data_protection);
remote_datawriter_crypto *
crypto_remote_datawriter_crypto__new(
const remote_participant_crypto *participant,
DDS_Security_ProtectionKind meta_protection,
DDS_Security_BasicProtectionKind data_protection,
DDS_Security_DatareaderCryptoHandle local_reader_handle);
CryptoObject *
crypto_object_keep(
CryptoObject *obj);
void crypto_object_release(
CryptoObject *obj);
bool crypto_object_valid(
CryptoObject *obj,
CryptoObjectKind_t kind);
void crypto_object_free(
CryptoObject *obj);
local_participant_crypto *
crypto_local_participant_crypto__new(
DDS_Security_IdentityHandle participant_identity);
remote_participant_crypto *
crypto_remote_participant_crypto__new(
DDS_Security_IdentityHandle participant_identity);
participant_key_material *
crypto_participant_key_material_new(
const local_participant_crypto *pplocal);
struct CryptoObjectTable;
typedef uint32_t (*CryptoObjectHashFunction)(const void *obj);
typedef int (*CryptoObjectEqualFunction)(const void *ha, const void *hb);
typedef CryptoObject *(*CryptoObjectFindFunction)(const struct CryptoObjectTable *table, const void *arg);
struct CryptoObjectTable *
crypto_object_table_new(
CryptoObjectHashFunction hashfnc,
CryptoObjectEqualFunction equalfnc,
CryptoObjectFindFunction findfnc);
void crypto_object_table_free(
struct CryptoObjectTable *table);
CryptoObject *
crypto_object_table_insert(
struct CryptoObjectTable *table,
CryptoObject *object);
void crypto_object_table_remove_object(
struct CryptoObjectTable *table,
CryptoObject *object);
CryptoObject *
crypto_object_table_remove(
struct CryptoObjectTable *table,
int64_t handle);
CryptoObject *
crypto_object_table_find_by_template(
const struct CryptoObjectTable *table,
const void *template);
CryptoObject *
crypto_object_table_find(
struct CryptoObjectTable *table,
int64_t handle);
typedef int (*CryptoObjectTableCallback)(CryptoObject *obj, void *arg);
struct CryptoObjectTable
{
struct ddsrt_hh *htab;
ddsrt_mutex_t lock;
CryptoObjectFindFunction findfnc;
};
void crypto_object_table_walk(
struct CryptoObjectTable *table,
CryptoObjectTableCallback callback,
void *arg);
#endif /* CRYPTO_OBJECTS_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTO_TRANSFORM_H
#define CRYPTO_TRANSFORM_H
#include "dds/security/dds_security_api.h"
/**
* @brief Allocation function for implementer structure (with internal variables) transparently.
*/
dds_security_crypto_transform *
dds_security_crypto_transform__alloc(
const dds_security_cryptography *crypto);
void
dds_security_crypto_transform__dealloc(
dds_security_crypto_transform *instance);
#endif /* CRYPTO_TRANSFORM_H */

View file

@ -0,0 +1,153 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include "dds/ddsrt/bswap.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/string.h"
#include "dds/ddsrt/types.h"
#include "dds/security/dds_security_api.h"
#include "dds/security/core/dds_security_utils.h"
#include "crypto_defs.h"
#include "crypto_utils.h"
char *crypto_openssl_error_message(void)
{
BIO *bio = BIO_new(BIO_s_mem());
char *msg;
char *buf = NULL;
size_t len;
if (!bio)
return ddsrt_strdup ("BIO_new failed");
ERR_print_errors(bio);
len = (size_t) BIO_get_mem_data(bio, &buf);
msg = ddsrt_malloc(len + 1);
memset(msg, 0, len + 1);
memcpy(msg, buf, len);
BIO_free(bio);
return msg;
}
static bool
crypto_calculate_key_impl(
const char *prefix,
crypto_session_key_t *session_key,
uint32_t session_id,
const unsigned char *master_salt,
const unsigned char *master_key,
DDS_Security_CryptoTransformKind_Enum transformation_kind,
DDS_Security_SecurityException *ex)
{
uint32_t key_bytes = CRYPTO_KEY_SIZE_BYTES(transformation_kind);
uint32_t id = ddsrt_toBE4u(session_id);
size_t sz = strlen(prefix) + key_bytes + sizeof(id);
unsigned char *buffer = ddsrt_malloc (sz);
unsigned char md[EVP_MAX_MD_SIZE];
memcpy(buffer, prefix, strlen(prefix));
memcpy(&buffer[strlen(prefix)], master_salt, key_bytes);
memcpy(&buffer[strlen(prefix) + key_bytes], &id, sizeof(id));
if (HMAC(EVP_sha256(), master_key, (int)key_bytes, buffer, sz, md, NULL) == NULL)
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "HMAC failed: ");
ddsrt_free (buffer);
return false;
}
memcpy (session_key->data, md, key_bytes);
ddsrt_free (buffer);
return true;
}
bool
crypto_calculate_session_key(
crypto_session_key_t *session_key,
uint32_t session_id,
const unsigned char *master_salt,
const unsigned char *master_key,
DDS_Security_CryptoTransformKind_Enum transformation_kind,
DDS_Security_SecurityException *ex)
{
return crypto_calculate_key_impl("SessionKey", session_key, session_id, master_salt, master_key, transformation_kind, ex);
}
bool
crypto_calculate_receiver_specific_key(
crypto_session_key_t *session_key,
uint32_t session_id,
const unsigned char *master_salt,
const unsigned char *master_key,
DDS_Security_CryptoTransformKind_Enum transformation_kind,
DDS_Security_SecurityException *ex)
{
return crypto_calculate_key_impl("SessionReceiverKey", session_key, session_id, master_salt, master_key, transformation_kind, ex);
}
uint32_t
crypto_get_key_size(
DDS_Security_CryptoTransformKind_Enum kind)
{
switch (kind)
{
case CRYPTO_TRANSFORMATION_KIND_AES128_GMAC:
case CRYPTO_TRANSFORMATION_KIND_AES128_GCM:
return 128;
case CRYPTO_TRANSFORMATION_KIND_AES256_GMAC:
case CRYPTO_TRANSFORMATION_KIND_AES256_GCM:
return 256;
default:
return 0;
}
}
uint32_t
crypto_get_random_uint32(void)
{
uint32_t val;
RAND_bytes((unsigned char *)&val, sizeof(uint32_t));
return val;
}
uint64_t
crypto_get_random_uint64(void)
{
uint64_t val;
RAND_bytes((unsigned char *)&val, sizeof(uint64_t));
return val;
}
unsigned char *
crypto_hmac256(
const unsigned char *key,
uint32_t key_size,
const unsigned char *data,
uint32_t data_size,
DDS_Security_SecurityException *ex)
{
unsigned char md[EVP_MAX_MD_SIZE];
unsigned char *result;
assert (key_size <= INT32_MAX);
if (HMAC(EVP_sha256(), key, (int) key_size, data, data_size, md, NULL) == NULL)
{
DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, 0, "Failed to init hashing context: ");
return NULL;
}
result = ddsrt_malloc(key_size);
memcpy (result, md, key_size);
return result;
}

View file

@ -0,0 +1,95 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTO_UTILS_H
#define CRYPTO_UTILS_H
#include "dds/ddsrt/bswap.h"
#include "dds/ddsrt/endian.h"
#include "dds/ddsrt/types.h"
#include "dds/security/export.h"
#include "dds/security/dds_security_api.h"
#include "dds/security/core/dds_security_types.h"
#include "crypto_defs.h"
#define CRYPTO_TRANSFORM_KIND(k) ddsrt_fromBE4u((*(uint32_t *)&((k)[0])))
#define CRYPTO_TRANSFORM_ID(k) ddsrt_fromBE4u((*(uint32_t *)&((k)[0])))
#define CRYPTO_KEY_SIZE_BYTES(kind) (crypto_get_key_size(kind) >> 3)
#define ALIGN4(x) (((x) + 3) & (uint32_t)(-4))
struct init_vector_suffix
{
uint32_t high;
uint32_t low;
};
/**
* Return a string that contains an openssl error description
* When a openssl function returns an error this function can be
* used to retrieve a descriptive error string.
* Note that the returned string should be freed.
*/
char *crypto_openssl_error_message(void);
/**
* @param[in,out] session_key Session key
* @param[in] session_id Session Id
* @param[in] master_salt Master salt
* @param[in] master_key Master key
* @param[in] transformation_kind Transformation kind
* @param[in,out] ex Security exception
*/
SECURITY_EXPORT bool crypto_calculate_session_key(
crypto_session_key_t *session_key,
uint32_t session_id,
const unsigned char *master_salt,
const unsigned char *master_key,
DDS_Security_CryptoTransformKind_Enum transformation_kind,
DDS_Security_SecurityException *ex);
/**
* @param[in,out] session_key Session key
* @param[in] session_id Session Id
* @param[in] master_salt Master salt
* @param[in] master_key Master key
* @param[in] transformation_kind Transformation kind
* @param[in,out] ex Security exception
*/
SECURITY_EXPORT bool crypto_calculate_receiver_specific_key(
crypto_session_key_t *session_key,
uint32_t session_id,
const unsigned char *master_salt,
const unsigned char *master_key,
DDS_Security_CryptoTransformKind_Enum transformation_kind,
DDS_Security_SecurityException *ex);
SECURITY_EXPORT uint32_t crypto_get_key_size(DDS_Security_CryptoTransformKind_Enum kind);
SECURITY_EXPORT uint32_t crypto_get_random_uint32(void);
SECURITY_EXPORT uint64_t crypto_get_random_uint64(void);
/**
* @brief Compute a HMAC256 on the provided data.
*
* @param[in] key The key used to compute the HMAC256 result
* @param[in] key_size The size of the key (128 or 256 bits)
* @param[in] data The data on which the HMAC is computed
* @param[in] data_size The size of the data
* @param[in,out] ex Security exception
*/
SECURITY_EXPORT unsigned char *crypto_hmac256(
const unsigned char *key,
uint32_t key_size,
const unsigned char *data,
uint32_t data_size,
DDS_Security_SecurityException *ex);
#endif /* CRYPTO_UTILS_H */

View file

@ -0,0 +1,98 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/types.h"
#include "dds/security/dds_security_api.h"
#include "cryptography.h"
#include "crypto_key_exchange.h"
#include "crypto_key_factory.h"
#include "crypto_transform.h"
/**
* Implementation structure for storing encapsulated members of the instance
* while giving only the interface definition to user
*/
typedef struct dds_security_cryptography_impl {
dds_security_cryptography base;
} dds_security_cryptography_impl;
dds_security_crypto_key_factory *cryptography_get_crypto_key_factory (const struct dds_security_cryptography *crypto)
{
const dds_security_cryptography_impl *instance = (dds_security_cryptography_impl *) crypto;
return instance->base.crypto_key_factory;
}
dds_security_crypto_key_exchange *cryptography_get_crypto_key_exchange (const struct dds_security_cryptography *crypto)
{
const dds_security_cryptography_impl *instance = (dds_security_cryptography_impl *) crypto;
return instance->base.crypto_key_exchange;
}
dds_security_crypto_transform *cryptography_get_crypto_transform (const struct dds_security_cryptography *crypto)
{
const dds_security_cryptography_impl *instance = (dds_security_cryptography_impl *) crypto;
return instance->base.crypto_transform;
}
int init_crypto (const char *argument, void **context)
{
dds_security_cryptography_impl *cryptography;
dds_security_crypto_key_exchange *crypto_key_exchange;
dds_security_crypto_key_factory *crypto_key_factory;
dds_security_crypto_transform *crypto_transform;
DDSRT_UNUSED_ARG (argument);
/* allocate new instance */
cryptography = ddsrt_malloc (sizeof(*cryptography));
/* assign the sub components */
crypto_key_exchange = dds_security_crypto_key_exchange__alloc ((dds_security_cryptography *)cryptography);
if (!crypto_key_exchange) goto err_exchange;
crypto_key_factory = dds_security_crypto_key_factory__alloc ((dds_security_cryptography *)cryptography);
if (!crypto_key_factory) goto err_factory;
crypto_transform = dds_security_crypto_transform__alloc ((dds_security_cryptography *)cryptography);
if (!crypto_transform) goto err_transform;
cryptography->base.crypto_key_exchange = crypto_key_exchange;
cryptography->base.crypto_key_factory = crypto_key_factory;
cryptography->base.crypto_transform = crypto_transform;
/* return the instance */
*context = cryptography;
return DDS_SECURITY_SUCCESS;
err_transform:
dds_security_crypto_key_factory__dealloc (crypto_key_factory);
err_factory:
dds_security_crypto_key_exchange__dealloc (crypto_key_exchange);
err_exchange:
ddsrt_free (cryptography);
*context = NULL;
return DDS_SECURITY_FAILED;
}
int finalize_crypto (void *instance)
{
dds_security_cryptography_impl* instance_impl = (dds_security_cryptography_impl*) instance;
/* deallocate components */
dds_security_crypto_key_exchange__dealloc (instance_impl->base.crypto_key_exchange);
dds_security_crypto_key_factory__dealloc (instance_impl->base.crypto_key_factory);
dds_security_crypto_transform__dealloc (instance_impl->base.crypto_transform);
/* deallocate cryptography */
ddsrt_free (instance_impl);
return DDS_SECURITY_SUCCESS;
}

View file

@ -0,0 +1,33 @@
/*
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CRYPTOGRAPHY_H
#define CRYPTOGRAPHY_H
#include "dds/security/dds_security_api.h"
#include "dds/security/export.h"
SECURITY_EXPORT int init_crypto(const char *argument, void **context);
SECURITY_EXPORT int finalize_crypto(void *instance);
dds_security_crypto_key_factory *
cryptography_get_crypto_key_factory(
const dds_security_cryptography *crypto);
dds_security_crypto_key_exchange *
cryptography_get_crypto_key_exchange(
const dds_security_cryptography *crypto);
dds_security_crypto_transform *
cryptography_get_crypto_transform(
const dds_security_cryptography *crypto);
#endif /* CRYPTOGRAPHY_H */