diff options
Diffstat (limited to 'libtransport/src/implementation')
-rw-r--r-- | libtransport/src/implementation/CMakeLists.txt | 13 | ||||
-rw-r--r-- | libtransport/src/implementation/p2psecure_socket_consumer.cc | 370 | ||||
-rw-r--r-- | libtransport/src/implementation/p2psecure_socket_consumer.h | 134 | ||||
-rw-r--r-- | libtransport/src/implementation/p2psecure_socket_producer.cc | 347 | ||||
-rw-r--r-- | libtransport/src/implementation/p2psecure_socket_producer.h | 114 | ||||
-rw-r--r-- | libtransport/src/implementation/socket.cc | 4 | ||||
-rw-r--r-- | libtransport/src/implementation/socket.h | 4 | ||||
-rw-r--r-- | libtransport/src/implementation/socket_consumer.h | 90 | ||||
-rw-r--r-- | libtransport/src/implementation/socket_producer.h | 43 | ||||
-rw-r--r-- | libtransport/src/implementation/tls_rtc_socket_producer.cc | 208 | ||||
-rw-r--r-- | libtransport/src/implementation/tls_rtc_socket_producer.h | 57 | ||||
-rw-r--r-- | libtransport/src/implementation/tls_socket_consumer.cc | 343 | ||||
-rw-r--r-- | libtransport/src/implementation/tls_socket_consumer.h | 110 | ||||
-rw-r--r-- | libtransport/src/implementation/tls_socket_producer.cc | 550 | ||||
-rw-r--r-- | libtransport/src/implementation/tls_socket_producer.h | 154 |
15 files changed, 111 insertions, 2430 deletions
diff --git a/libtransport/src/implementation/CMakeLists.txt b/libtransport/src/implementation/CMakeLists.txt index 1f2a33a4c..c759dd964 100644 --- a/libtransport/src/implementation/CMakeLists.txt +++ b/libtransport/src/implementation/CMakeLists.txt @@ -19,21 +19,8 @@ list(APPEND HEADER_FILES if (${OPENSSL_VERSION} VERSION_EQUAL "1.1.1a" OR ${OPENSSL_VERSION} VERSION_GREATER "1.1.1a") list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_producer.cc - # ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.cc - ${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_producer.cc - ${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.cc - ${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_consumer.cc ${CMAKE_CURRENT_SOURCE_DIR}/socket.cc ) - - list(APPEND HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_producer.h - # ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.h - ${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_producer.h - ${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.h - ${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_consumer.h - ) endif() set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.cc b/libtransport/src/implementation/p2psecure_socket_consumer.cc deleted file mode 100644 index 6b67a5487..000000000 --- a/libtransport/src/implementation/p2psecure_socket_consumer.cc +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <implementation/p2psecure_socket_consumer.h> -#include <interfaces/tls_socket_consumer.h> -#include <openssl/bio.h> -#include <openssl/ssl.h> -#include <openssl/tls1.h> - -#include <random> - -namespace transport { -namespace implementation { - -void P2PSecureConsumerSocket::setInterestPayload( - interface::ConsumerSocket &c, const core::Interest &interest) { - Interest &int2 = const_cast<Interest &>(interest); - random_suffix_ = int2.getName().getSuffix(); - - if (payload_ != NULL) int2.appendPayload(std::move(payload_)); -} - -/* Return the number of read bytes in the return param */ -int readOld(BIO *b, char *buf, int size) { - if (size < 0) return size; - - P2PSecureConsumerSocket *socket; - socket = (P2PSecureConsumerSocket *)BIO_get_data(b); - - std::unique_lock<std::mutex> lck(socket->mtx_); - - if (!socket->something_to_read_) { - if (!socket->transport_protocol_->isRunning()) { - socket->network_name_.setSuffix(socket->random_suffix_); - socket->ConsumerSocket::consume(socket->network_name_); - } - - if (!socket->something_to_read_) socket->cv_.wait(lck); - } - - size_t size_to_read, read; - size_t chain_size = socket->head_->length(); - - if (socket->head_->isChained()) - chain_size = socket->head_->computeChainDataLength(); - - if (chain_size > (size_t)size) { - read = size_to_read = (size_t)size; - } else { - read = size_to_read = chain_size; - socket->something_to_read_ = false; - } - - while (size_to_read) { - if (socket->head_->length() < size_to_read) { - std::memcpy(buf, socket->head_->data(), socket->head_->length()); - size_to_read -= socket->head_->length(); - buf += socket->head_->length(); - socket->head_ = socket->head_->pop(); - } else { - std::memcpy(buf, socket->head_->data(), size_to_read); - socket->head_->trimStart(size_to_read); - size_to_read = 0; - } - } - - return (int)read; -} - -/* Return the number of read bytes in readbytes */ -int read(BIO *b, char *buf, size_t size, size_t *readbytes) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = readOld(b, buf, (int)size); - - if (ret <= 0) { - *readbytes = 0; - return ret; - } - - *readbytes = (size_t)ret; - - return 1; -} - -/* Return the number of written bytes in the return param */ -int writeOld(BIO *b, const char *buf, int num) { - P2PSecureConsumerSocket *socket; - socket = (P2PSecureConsumerSocket *)BIO_get_data(b); - - socket->payload_ = utils::MemBuf::copyBuffer(buf, num); - - socket->ConsumerSocket::setSocketOption( - ConsumerCallbacksOptions::INTEREST_OUTPUT, - (ConsumerInterestCallback)std::bind( - &P2PSecureConsumerSocket::setInterestPayload, socket, - std::placeholders::_1, std::placeholders::_2)); - - return num; -} - -/* Return the number of written bytes in written */ -int write(BIO *b, const char *buf, size_t size, size_t *written) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = writeOld(b, buf, (int)size); - - if (ret <= 0) { - *written = 0; - return ret; - } - - *written = (size_t)ret; - - return 1; -} - -long ctrl(BIO *b, int cmd, long num, void *ptr) { return 1; } - -int P2PSecureConsumerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, - const unsigned char **out, - size_t *outlen, X509 *x, - size_t chainidx, int *al, - void *add_arg) { - if (ext_type == 100) { - *out = (unsigned char *)malloc(4); - *(uint32_t *)*out = 10; - *outlen = 4; - } - return 1; -} - -void P2PSecureConsumerSocket::freeHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, - const unsigned char *out, - void *add_arg) { - free(const_cast<unsigned char *>(out)); -} - -int P2PSecureConsumerSocket::parseHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, - const unsigned char *in, - size_t inlen, X509 *x, - size_t chainidx, int *al, - void *add_arg) { - P2PSecureConsumerSocket *socket = - reinterpret_cast<P2PSecureConsumerSocket *>(add_arg); - if (ext_type == 100) { - memcpy(&socket->secure_prefix_, in, sizeof(ip_prefix_t)); - } - return 1; -} - -P2PSecureConsumerSocket::P2PSecureConsumerSocket( - interface::ConsumerSocket *consumer, int handshake_protocol, - int transport_protocol) - : ConsumerSocket(consumer, handshake_protocol), - name_(), - tls_consumer_(nullptr), - decrypted_content_(), - payload_(), - head_(), - something_to_read_(false), - content_downloaded_(false), - random_suffix_(), - secure_prefix_(), - producer_namespace_(), - read_callback_decrypted_(), - mtx_(), - cv_(), - protocol_(transport_protocol) { - /* Create the (d)TLS state */ - const SSL_METHOD *meth = TLS_client_method(); - ctx_ = SSL_CTX_new(meth); - - int result = - SSL_CTX_set_ciphersuites(ctx_, - "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_" - "SHA256:TLS_AES_128_GCM_SHA256"); - if (result != 1) { - throw errors::RuntimeException( - "Unable to set cipher list on TLS subsystem. Aborting."); - } - - SSL_CTX_set_min_proto_version(ctx_, TLS1_3_VERSION); - SSL_CTX_set_max_proto_version(ctx_, TLS1_3_VERSION); - SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, NULL); - SSL_CTX_set_ssl_version(ctx_, meth); - - result = SSL_CTX_add_custom_ext( - ctx_, 100, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, - P2PSecureConsumerSocket::addHicnKeyIdCb, - P2PSecureConsumerSocket::freeHicnKeyIdCb, NULL, - P2PSecureConsumerSocket::parseHicnKeyIdCb, this); - - ssl_ = SSL_new(ctx_); - - bio_meth_ = BIO_meth_new(BIO_TYPE_CONNECT, "secure consumer socket"); - BIO_meth_set_read(bio_meth_, readOld); - BIO_meth_set_write(bio_meth_, writeOld); - BIO_meth_set_ctrl(bio_meth_, ctrl); - BIO *bio = BIO_new(bio_meth_); - BIO_set_init(bio, 1); - BIO_set_data(bio, this); - SSL_set_bio(ssl_, bio, bio); - - std::default_random_engine generator; - std::uniform_int_distribution<int> distribution( - 1, std::numeric_limits<uint32_t>::max()); - random_suffix_ = 0; - - this->ConsumerSocket::setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, - this); -}; - -P2PSecureConsumerSocket::~P2PSecureConsumerSocket() { - BIO_meth_free(bio_meth_); - SSL_shutdown(ssl_); -} - -int P2PSecureConsumerSocket::handshake() { - int result = 1; - - if (!(SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) { - return 1; - } - - ConsumerSocket::getSocketOption(MAX_WINDOW_SIZE, old_max_win_); - ConsumerSocket::getSocketOption(CURRENT_WINDOW_SIZE, old_current_win_); - - ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, (double)1.0); - ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, (double)1.0); - - network_name_ = producer_namespace_.getRandomName(); - network_name_.setSuffix(0); - - DLOG_IF(INFO, VLOG_IS_ON(2)) << "Start handshake at " << network_name_; - result = SSL_connect(this->ssl_); - - return result; -} - -void P2PSecureConsumerSocket::initSessionSocket() { - tls_consumer_ = - std::make_shared<TLSConsumerSocket>(nullptr, this->protocol_, this->ssl_); - tls_consumer_->setInterface( - new interface::TLSConsumerSocket(tls_consumer_.get())); - - ConsumerTimerCallback *stats_summary_callback = nullptr; - this->getSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY, - &stats_summary_callback); - - uint32_t lifetime; - this->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME, lifetime); - - tls_consumer_->setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME, - lifetime); - tls_consumer_->setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, - read_callback_decrypted_); - tls_consumer_->setSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY, - *stats_summary_callback); - tls_consumer_->setSocketOption(GeneralTransportOptions::STATS_INTERVAL, - this->timer_interval_milliseconds_); - tls_consumer_->setSocketOption(MAX_WINDOW_SIZE, old_max_win_); - tls_consumer_->setSocketOption(CURRENT_WINDOW_SIZE, old_current_win_); - tls_consumer_->connect(); -} - -int P2PSecureConsumerSocket::consume(const Name &name) { - if (transport_protocol_->isRunning()) { - return CONSUMER_BUSY; - } - - if (handshake() != 1) { - throw errors::RuntimeException("Unable to perform client handshake"); - } else { - DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!"; - } - - initSessionSocket(); - - if (tls_consumer_ == nullptr) { - throw errors::RuntimeException("TLS socket does not exist"); - } - - std::shared_ptr<Name> prefix_name = std::make_shared<Name>( - secure_prefix_.family, - ip_address_get_buffer(&(secure_prefix_.address), secure_prefix_.family)); - std::shared_ptr<Prefix> prefix = - std::make_shared<Prefix>(*prefix_name, secure_prefix_.len); - - if (payload_ != nullptr) - return tls_consumer_->consume((prefix->mapName(name)), std::move(payload_)); - else - return tls_consumer_->consume((prefix->mapName(name))); -} - -void P2PSecureConsumerSocket::registerPrefix(const Prefix &producer_namespace) { - producer_namespace_ = producer_namespace; -} - -int P2PSecureConsumerSocket::setSocketOption( - int socket_option_key, ReadCallback *socket_option_value) { - return rescheduleOnIOService( - socket_option_key, socket_option_value, - [this](int socket_option_key, ReadCallback *socket_option_value) -> int { - switch (socket_option_key) { - case ConsumerCallbacksOptions::READ_CALLBACK: - read_callback_decrypted_ = socket_option_value; - break; - default: - return SOCKET_OPTION_NOT_SET; - } - - return SOCKET_OPTION_SET; - }); -} - -void P2PSecureConsumerSocket::getReadBuffer(uint8_t **application_buffer, - size_t *max_length){}; - -void P2PSecureConsumerSocket::readDataAvailable(size_t length) noexcept {}; - -size_t P2PSecureConsumerSocket::maxBufferSize() const { - return SSL3_RT_MAX_PLAIN_LENGTH; -} - -void P2PSecureConsumerSocket::readBufferAvailable( - std::unique_ptr<utils::MemBuf> &&buffer) noexcept { - std::unique_lock<std::mutex> lck(this->mtx_); - if (head_) { - head_->prependChain(std::move(buffer)); - } else { - head_ = std::move(buffer); - } - - something_to_read_ = true; - cv_.notify_one(); -} - -void P2PSecureConsumerSocket::readError(const std::error_code &ec) noexcept {}; - -void P2PSecureConsumerSocket::readSuccess(std::size_t total_size) noexcept { - std::unique_lock<std::mutex> lck(this->mtx_); - content_downloaded_ = true; - something_to_read_ = true; - cv_.notify_one(); -} - -bool P2PSecureConsumerSocket::isBufferMovable() noexcept { return true; } - -} // namespace implementation -} // namespace transport diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.h b/libtransport/src/implementation/p2psecure_socket_consumer.h deleted file mode 100644 index a5e69f611..000000000 --- a/libtransport/src/implementation/p2psecure_socket_consumer.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <hicn/transport/interfaces/socket_consumer.h> -#include <implementation/tls_socket_consumer.h> -#include <openssl/bio.h> -#include <openssl/ssl.h> - -namespace transport { -namespace implementation { - -class P2PSecureConsumerSocket : public ConsumerSocket, - public interface::ConsumerSocket::ReadCallback { - /* Return the number of read bytes in readbytes */ - friend int read(BIO *b, char *buf, size_t size, size_t *readbytes); - - /* Return the number of read bytes in the return param */ - friend int readOld(BIO *h, char *buf, int size); - - /* Return the number of written bytes in written */ - friend int write(BIO *b, const char *buf, size_t size, size_t *written); - - /* Return the number of written bytes in the return param */ - friend int writeOld(BIO *h, const char *buf, int num); - - friend long ctrl(BIO *b, int cmd, long num, void *ptr); - - public: - explicit P2PSecureConsumerSocket(interface::ConsumerSocket *consumer, - int handshake_protocol, - int transport_protocol); - - ~P2PSecureConsumerSocket(); - - int consume(const Name &name) override; - - void registerPrefix(const Prefix &producer_namespace); - - int setSocketOption( - int socket_option_key, - interface::ConsumerSocket::ReadCallback *socket_option_value) override; - - using ConsumerSocket::getSocketOption; - using ConsumerSocket::setSocketOption; - - protected: - /* Callback invoked once an interest has been received and its payload - * decrypted */ - ConsumerInterestCallback on_interest_input_decrypted_; - ConsumerInterestCallback on_interest_process_decrypted_; - - private: - Name name_; - std::shared_ptr<TLSConsumerSocket> tls_consumer_; - /* SSL handle */ - SSL *ssl_; - SSL_CTX *ctx_; - BIO_METHOD *bio_meth_; - /* Chain of MemBuf to be used as a temporary buffer to pass descypted data - * from the underlying layer to the application */ - std::unique_ptr<utils::MemBuf> decrypted_content_; - /* Chain of MemBuf holding the payload to be written into interest or data */ - std::unique_ptr<utils::MemBuf> payload_; - /* Chain of MemBuf holding the data retrieved from the underlying layer */ - std::unique_ptr<utils::MemBuf> head_; - bool something_to_read_; - bool content_downloaded_; - double old_max_win_; - double old_current_win_; - uint32_t random_suffix_; - ip_prefix_t secure_prefix_; - Prefix producer_namespace_; - interface::ConsumerSocket::ReadCallback *read_callback_decrypted_; - std::mutex mtx_; - - /* Condition variable for the wait */ - std::condition_variable cv_; - - int protocol_; - - void setInterestPayload(interface::ConsumerSocket &c, - const core::Interest &interest); - - static int addHicnKeyIdCb(SSL *s, unsigned int ext_type, unsigned int context, - const unsigned char **out, size_t *outlen, X509 *x, - size_t chainidx, int *al, void *add_arg); - - static void freeHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, const unsigned char *out, - void *add_arg); - - static int parseHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, const unsigned char *in, - size_t inlen, X509 *x, size_t chainidx, int *al, - void *add_arg); - - virtual void getReadBuffer(uint8_t **application_buffer, - size_t *max_length) override; - - virtual void readDataAvailable(size_t length) noexcept override; - - virtual size_t maxBufferSize() const override; - - virtual void readBufferAvailable( - std::unique_ptr<utils::MemBuf> &&buffer) noexcept override; - - virtual void readError(const std::error_code &ec) noexcept override; - - virtual void readSuccess(std::size_t total_size) noexcept override; - - virtual bool isBufferMovable() noexcept override; - - int handshake(); - - void initSessionSocket(); -}; - -} // namespace implementation - -} // end namespace transport diff --git a/libtransport/src/implementation/p2psecure_socket_producer.cc b/libtransport/src/implementation/p2psecure_socket_producer.cc deleted file mode 100644 index ee78ea53b..000000000 --- a/libtransport/src/implementation/p2psecure_socket_producer.cc +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <hicn/transport/core/interest.h> -#include <implementation/p2psecure_socket_producer.h> -// #include <implementation/tls_rtc_socket_producer.h> -#include <implementation/tls_socket_producer.h> -#include <interfaces/tls_rtc_socket_producer.h> -#include <interfaces/tls_socket_producer.h> -#include <openssl/bio.h> -#include <openssl/pkcs12.h> -#include <openssl/rand.h> -#include <openssl/ssl.h> - -namespace transport { -namespace implementation { - -/* Workaround to prevent content with expiry time equal to 0 to be lost when - * pushed in the forwarder */ -#define HICN_HANDSHAKE_CONTENT_EXPIRY_TIME 100; - -P2PSecureProducerSocket::P2PSecureProducerSocket( - interface::ProducerSocket *producer_socket) - : ProducerSocket(producer_socket, - ProductionProtocolAlgorithms::BYTE_STREAM), - mtx_(), - cv_(), - map_producers(), - list_producers() {} - -P2PSecureProducerSocket::P2PSecureProducerSocket( - interface::ProducerSocket *producer_socket, bool rtc, - std::string &keystore_path, std::string &keystore_pwd) - : ProducerSocket(producer_socket, - ProductionProtocolAlgorithms::BYTE_STREAM), - rtc_(rtc), - mtx_(), - cv_(), - map_producers(), - list_producers() { - /* Setup SSL context (identity and parameter to use TLS 1.3) */ - FILE *p12file = fopen(keystore_path.c_str(), "r"); - if (p12file == NULL) - throw errors::RuntimeException("impossible open keystore"); - std::unique_ptr<PKCS12, decltype(&::PKCS12_free)> p12( - d2i_PKCS12_fp(p12file, NULL), ::PKCS12_free); - // now we parse the file to get the first key and certificate - if (1 != PKCS12_parse(p12.get(), keystore_pwd.c_str(), &pkey_rsa_, &cert_509_, - NULL)) - throw errors::RuntimeException("impossible to get the private key"); - fclose(p12file); - - /* Set the callback so that when an interest is received we catch it and we - * decrypt the payload before passing it to the application. */ - ProducerSocket::setSocketOption( - ProducerCallbacksOptions::INTEREST_INPUT, - (ProducerInterestCallback)std::bind( - &P2PSecureProducerSocket::onInterestCallback, this, - std::placeholders::_1, std::placeholders::_2)); -} - -P2PSecureProducerSocket::~P2PSecureProducerSocket() {} - -void P2PSecureProducerSocket::initSessionSocket( - std::unique_ptr<TLSProducerSocket> &producer) { - producer->on_content_produced_application_ = - this->on_content_produced_application_; - producer->setSocketOption(CONTENT_OBJECT_EXPIRY_TIME, - this->content_object_expiry_time_); - producer->setSocketOption(SIGNER, this->signer_); - producer->setSocketOption(MAKE_MANIFEST, this->making_manifest_); - producer->setSocketOption(DATA_PACKET_SIZE, - (uint32_t)(this->data_packet_size_)); - uint32_t output_buffer_size = 0; - this->getSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, - output_buffer_size); - producer->setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, - output_buffer_size); - - if (!rtc_) { - producer->setInterface(new interface::TLSProducerSocket(producer.get())); - } else { - // TODO - // TLSRTCProducerSocket *rtc_producer = - // dynamic_cast<TLSRTCProducerSocket *>(producer.get()); - // rtc_producer->setInterface( - // new interface::TLSRTCProducerSocket(rtc_producer)); - } -} - -void P2PSecureProducerSocket::onInterestCallback(interface::ProducerSocket &p, - Interest &interest) { - std::unique_lock<std::mutex> lck(mtx_); - std::unique_ptr<TLSProducerSocket> tls_producer; - auto it = map_producers.find(interest.getName()); - - if (it != map_producers.end()) { - return; - } - - if (!rtc_) { - tls_producer = - std::make_unique<TLSProducerSocket>(nullptr, this, interest.getName()); - } else { - // TODO - // tls_producer = std::make_unique<TLSRTCProducerSocket>(nullptr, this, - // interest.getName()); - } - - initSessionSocket(tls_producer); - TLSProducerSocket *tls_producer_ptr = tls_producer.get(); - map_producers.insert({interest.getName(), move(tls_producer)}); - - DLOG_IF(INFO, VLOG_IS_ON(3)) << "Start handshake at " << interest.getName(); - - if (!rtc_) { - tls_producer_ptr->onInterest(*tls_producer_ptr, interest); - tls_producer_ptr->async_accept(); - } else { - // TODO - // TLSRTCProducerSocket *rtc_producer_ptr = - // dynamic_cast<TLSRTCProducerSocket *>(tls_producer_ptr); - // rtc_producer_ptr->onInterest(*rtc_producer_ptr, interest); - // rtc_producer_ptr->async_accept(); - } -} - -uint32_t P2PSecureProducerSocket::produceDatagram( - const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer) { - // TODO - throw errors::NotImplementedException(); - - // if (!rtc_) { - // throw errors::RuntimeException( - // "RTC must be the transport protocol to start the production of - // current " "data. Aborting."); - // } - - // std::unique_lock<std::mutex> lck(mtx_); - - // if (list_producers.empty()) cv_.wait(lck); - - // TODO - // for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - // { - // TLSRTCProducerSocket *rtc_producer = - // dynamic_cast<TLSRTCProducerSocket *>(it->get()); - // rtc_producer->produce(utils::MemBuf::copyBuffer(buffer, buffer_size)); - // } - - // return 0; -} - -uint32_t P2PSecureProducerSocket::produceStream( - const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer, - bool is_last, uint32_t start_offset) { - if (rtc_) { - throw errors::RuntimeException( - "RTC transport protocol is not compatible with the production of " - "current data. Aborting."); - } - - std::unique_lock<std::mutex> lck(mtx_); - uint32_t segments = 0; - - if (list_producers.empty()) cv_.wait(lck); - - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - segments += (*it)->produceStream(content_name, buffer->clone(), is_last, - start_offset); - - return segments; -} - -uint32_t P2PSecureProducerSocket::produceStream(const Name &content_name, - const uint8_t *buffer, - size_t buffer_size, - bool is_last, - uint32_t start_offset) { - if (rtc_) { - throw errors::RuntimeException( - "RTC transport protocol is not compatible with the production of " - "current data. Aborting."); - } - - std::unique_lock<std::mutex> lck(mtx_); - uint32_t segments = 0; - if (list_producers.empty()) cv_.wait(lck); - - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - segments += (*it)->produceStream(content_name, buffer, buffer_size, is_last, - start_offset); - - return segments; -} - -/* Redefinition of socket options to avoid name hiding */ -int P2PSecureProducerSocket::setSocketOption( - int socket_option_key, ProducerInterestCallback socket_option_value) { - if (!list_producers.empty()) { - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - } - - switch (socket_option_key) { - case ProducerCallbacksOptions::INTEREST_INPUT: - on_interest_input_decrypted_ = socket_option_value; - return SOCKET_OPTION_SET; - - case ProducerCallbacksOptions::INTEREST_DROP: - on_interest_dropped_input_buffer_ = socket_option_value; - return SOCKET_OPTION_SET; - - case ProducerCallbacksOptions::INTEREST_PASS: - on_interest_inserted_input_buffer_ = socket_option_value; - return SOCKET_OPTION_SET; - - case ProducerCallbacksOptions::CACHE_HIT: - on_interest_satisfied_output_buffer_ = socket_option_value; - return SOCKET_OPTION_SET; - - case ProducerCallbacksOptions::CACHE_MISS: - on_interest_process_decrypted_ = socket_option_value; - return SOCKET_OPTION_SET; - - default: - return SOCKET_OPTION_NOT_SET; - } -} - -int P2PSecureProducerSocket::setSocketOption( - int socket_option_key, - const std::shared_ptr<auth::Signer> &socket_option_value) { - if (!list_producers.empty()) - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - - switch (socket_option_key) { - case GeneralTransportOptions::SIGNER: { - signer_.reset(); - signer_ = socket_option_value; - - return SOCKET_OPTION_SET; - } - default: - return SOCKET_OPTION_NOT_SET; - } -} - -int P2PSecureProducerSocket::setSocketOption(int socket_option_key, - uint32_t socket_option_value) { - if (!list_producers.empty()) { - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - } - switch (socket_option_key) { - case GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME: - content_object_expiry_time_ = - socket_option_value; // HICN_HANDSHAKE_CONTENT_EXPIRY_TIME; - return SOCKET_OPTION_SET; - } - return ProducerSocket::setSocketOption(socket_option_key, - socket_option_value); -} - -int P2PSecureProducerSocket::setSocketOption(int socket_option_key, - bool socket_option_value) { - if (!list_producers.empty()) - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - - return ProducerSocket::setSocketOption(socket_option_key, - socket_option_value); -} - -int P2PSecureProducerSocket::setSocketOption(int socket_option_key, - Name *socket_option_value) { - if (!list_producers.empty()) - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - - return ProducerSocket::setSocketOption(socket_option_key, - socket_option_value); -} - -int P2PSecureProducerSocket::setSocketOption( - int socket_option_key, ProducerContentObjectCallback socket_option_value) { - if (!list_producers.empty()) - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - - return ProducerSocket::setSocketOption(socket_option_key, - socket_option_value); -} - -int P2PSecureProducerSocket::setSocketOption( - int socket_option_key, ProducerContentCallback socket_option_value) { - if (!list_producers.empty()) - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - - switch (socket_option_key) { - case ProducerCallbacksOptions::CONTENT_PRODUCED: - on_content_produced_application_ = socket_option_value; - break; - - default: - return SOCKET_OPTION_NOT_SET; - } - - return SOCKET_OPTION_SET; -} - -int P2PSecureProducerSocket::setSocketOption( - int socket_option_key, auth::CryptoHashType socket_option_value) { - if (!list_producers.empty()) - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - - return ProducerSocket::setSocketOption(socket_option_key, - socket_option_value); -} - -int P2PSecureProducerSocket::setSocketOption( - int socket_option_key, const std::string &socket_option_value) { - if (!list_producers.empty()) - for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) - (*it)->setSocketOption(socket_option_key, socket_option_value); - - return ProducerSocket::setSocketOption(socket_option_key, - socket_option_value); -} - -} // namespace implementation -} // namespace transport diff --git a/libtransport/src/implementation/p2psecure_socket_producer.h b/libtransport/src/implementation/p2psecure_socket_producer.h deleted file mode 100644 index 00f407a75..000000000 --- a/libtransport/src/implementation/p2psecure_socket_producer.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <hicn/transport/auth/signer.h> -#include <implementation/socket_producer.h> -// #include <implementation/tls_rtc_socket_producer.h> -#include <implementation/tls_socket_producer.h> -#include <openssl/ssl.h> -#include <utils/content_store.h> - -#include <condition_variable> -#include <forward_list> -#include <mutex> - -namespace transport { -namespace implementation { - -class P2PSecureProducerSocket : public ProducerSocket { - friend class TLSProducerSocket; - // TODO - // friend class TLSRTCProducerSocket; - - public: - explicit P2PSecureProducerSocket(interface::ProducerSocket *producer_socket); - - explicit P2PSecureProducerSocket(interface::ProducerSocket *producer_socket, - bool rtc, std::string &keystore_path, - std::string &keystore_pwd); - - ~P2PSecureProducerSocket(); - - uint32_t produceDatagram(const Name &content_name, - std::unique_ptr<utils::MemBuf> &&buffer) override; - - uint32_t produceStream(const Name &content_name, const uint8_t *buffer, - size_t buffer_size, bool is_last = true, - uint32_t start_offset = 0) override; - - uint32_t produceStream(const Name &content_name, - std::unique_ptr<utils::MemBuf> &&buffer, - bool is_last = true, - uint32_t start_offset = 0) override; - - int setSocketOption(int socket_option_key, - ProducerInterestCallback socket_option_value) override; - - int setSocketOption( - int socket_option_key, - const std::shared_ptr<auth::Signer> &socket_option_value) override; - - int setSocketOption(int socket_option_key, - uint32_t socket_option_value) override; - - int setSocketOption(int socket_option_key, bool socket_option_value) override; - - int setSocketOption(int socket_option_key, - Name *socket_option_value) override; - - int setSocketOption( - int socket_option_key, - ProducerContentObjectCallback socket_option_value) override; - - int setSocketOption(int socket_option_key, - ProducerContentCallback socket_option_value) override; - - int setSocketOption(int socket_option_key, - auth::CryptoHashType socket_option_value) override; - - int setSocketOption(int socket_option_key, - const std::string &socket_option_value) override; - - using ProducerSocket::getSocketOption; - // using ProducerSocket::onInterest; - - protected: - /* Callback invoked once an interest has been received and its payload - * decrypted */ - ProducerInterestCallback on_interest_input_decrypted_; - ProducerInterestCallback on_interest_process_decrypted_; - ProducerContentCallback on_content_produced_application_; - - private: - bool rtc_; - std::mutex mtx_; - /* Condition variable for the wait */ - std::condition_variable cv_; - X509 *cert_509_; - EVP_PKEY *pkey_rsa_; - std::unordered_map<core::Name, std::unique_ptr<TLSProducerSocket>, - core::hash<core::Name>, core::compare2<core::Name>> - map_producers; - std::list<std::unique_ptr<TLSProducerSocket>> list_producers; - - void onInterestCallback(interface::ProducerSocket &p, Interest &interest); - - void initSessionSocket(std::unique_ptr<TLSProducerSocket> &producer); -}; - -} // namespace implementation -} // namespace transport diff --git a/libtransport/src/implementation/socket.cc b/libtransport/src/implementation/socket.cc index 95941da07..b80fbb58c 100644 --- a/libtransport/src/implementation/socket.cc +++ b/libtransport/src/implementation/socket.cc @@ -23,7 +23,9 @@ namespace implementation { Socket::Socket(std::shared_ptr<core::Portal> &&portal) : portal_(std::move(portal)), is_async_(false), - packet_format_(interface::default_values::packet_format) {} + packet_format_(interface::default_values::packet_format), + signer_(std::make_shared<auth::VoidSigner>()), + verifier_(std::make_shared<auth::VoidVerifier>()) {} int Socket::setSocketOption(int socket_option_key, hicn_format_t packet_format) { diff --git a/libtransport/src/implementation/socket.h b/libtransport/src/implementation/socket.h index 11c9a704d..3eb93cff6 100644 --- a/libtransport/src/implementation/socket.h +++ b/libtransport/src/implementation/socket.h @@ -16,6 +16,8 @@ #pragma once #include <core/facade.h> +#include <hicn/transport/auth/signer.h> +#include <hicn/transport/auth/verifier.h> #include <hicn/transport/config.h> #include <hicn/transport/interfaces/callbacks.h> #include <hicn/transport/interfaces/socket_options_default_values.h> @@ -68,6 +70,8 @@ class Socket { std::shared_ptr<core::Portal> portal_; bool is_async_; hicn_format_t packet_format_; + std::shared_ptr<auth::Signer> signer_; + std::shared_ptr<auth::Verifier> verifier_; }; } // namespace implementation diff --git a/libtransport/src/implementation/socket_consumer.h b/libtransport/src/implementation/socket_consumer.h index 33e70888f..4721f426c 100644 --- a/libtransport/src/implementation/socket_consumer.h +++ b/libtransport/src/implementation/socket_consumer.h @@ -56,8 +56,8 @@ class ConsumerSocket : public Socket { rate_estimation_observer_(nullptr), rate_estimation_batching_parameter_(default_values::batch), rate_estimation_choice_(0), - unverified_interval_(default_values::unverified_interval), - unverified_ratio_(default_values::unverified_ratio), + manifest_factor_relevant_(default_values::manifest_factor_relevant), + manifest_factor_alert_(default_values::manifest_factor_alert), verifier_(std::make_shared<auth::VoidVerifier>()), verify_signature_(false), reset_window_(false), @@ -72,6 +72,8 @@ class ConsumerSocket : public Socket { timer_interval_milliseconds_(0), recovery_strategy_(RtcTransportRecoveryStrategies::RTX_ONLY), aggregated_data_(false), + content_sharing_mode_(false), + aggregated_interests_(false), guard_raaqm_params_() { switch (protocol) { case TransportProtocolAlgorithms::CBR: @@ -197,10 +199,6 @@ class ConsumerSocket : public Socket { current_window_size_ = socket_option_value; break; - case UNVERIFIED_RATIO: - unverified_ratio_ = socket_option_value; - break; - case GAMMA_VALUE: gamma_ = socket_option_value; break; @@ -242,10 +240,6 @@ class ConsumerSocket : public Socket { interest_lifetime_ = socket_option_value; break; - case GeneralTransportOptions::UNVERIFIED_INTERVAL: - unverified_interval_ = socket_option_value; - break; - case RateEstimationOptions::RATE_ESTIMATION_BATCH_PARAMETER: if (socket_option_value > 0) { rate_estimation_batching_parameter_ = socket_option_value; @@ -271,6 +265,14 @@ class ConsumerSocket : public Socket { (RtcTransportRecoveryStrategies)socket_option_value; break; + case MANIFEST_FACTOR_RELEVANT: + manifest_factor_relevant_ = socket_option_value; + break; + + case MANIFEST_FACTOR_ALERT: + manifest_factor_alert_ = socket_option_value; + break; + default: return SOCKET_OPTION_NOT_SET; } @@ -339,6 +341,16 @@ class ConsumerSocket : public Socket { result = SOCKET_OPTION_SET; break; + case RtcTransportOptions::CONTENT_SHARING_MODE: + content_sharing_mode_ = socket_option_value; + result = SOCKET_OPTION_SET; + break; + + case RtcTransportOptions::AGGREGATED_INTERESTS: + aggregated_interests_ = socket_option_value; + result = SOCKET_OPTION_SET; + break; + default: return result; } @@ -416,6 +428,22 @@ class ConsumerSocket : public Socket { int setSocketOption( int socket_option_key, + const std::shared_ptr<auth::Signer> &socket_option_value) { + if (!transport_protocol_->isRunning()) { + switch (socket_option_key) { + case GeneralTransportOptions::SIGNER: + signer_.reset(); + signer_ = socket_option_value; + break; + default: + return SOCKET_OPTION_NOT_SET; + } + } + return SOCKET_OPTION_SET; + } + + int setSocketOption( + int socket_option_key, const std::shared_ptr<auth::Verifier> &socket_option_value) { if (!transport_protocol_->isRunning()) { switch (socket_option_key) { @@ -506,10 +534,6 @@ class ConsumerSocket : public Socket { socket_option_value = current_window_size_; break; - case GeneralTransportOptions::UNVERIFIED_RATIO: - socket_option_value = unverified_ratio_; - break; - // RAAQM parameters case RaaqmTransportOptions::GAMMA_VALUE: @@ -550,10 +574,6 @@ class ConsumerSocket : public Socket { socket_option_value = interest_lifetime_; break; - case GeneralTransportOptions::UNVERIFIED_INTERVAL: - socket_option_value = unverified_interval_; - break; - case RaaqmTransportOptions::SAMPLE_NUMBER: socket_option_value = sample_number_; break; @@ -574,6 +594,14 @@ class ConsumerSocket : public Socket { socket_option_value = recovery_strategy_; break; + case GeneralTransportOptions::MANIFEST_FACTOR_RELEVANT: + socket_option_value = manifest_factor_relevant_; + break; + + case GeneralTransportOptions::MANIFEST_FACTOR_ALERT: + socket_option_value = manifest_factor_alert_; + break; + default: return SOCKET_OPTION_NOT_GET; } @@ -599,6 +627,14 @@ class ConsumerSocket : public Socket { socket_option_value = aggregated_data_; break; + case RtcTransportOptions::CONTENT_SHARING_MODE: + socket_option_value = content_sharing_mode_; + break; + + case RtcTransportOptions::AGGREGATED_INTERESTS: + socket_option_value = aggregated_interests_; + break; + default: return SOCKET_OPTION_NOT_GET; } @@ -689,6 +725,18 @@ class ConsumerSocket : public Socket { } int getSocketOption(int socket_option_key, + std::shared_ptr<auth::Signer> &socket_option_value) { + switch (socket_option_key) { + case GeneralTransportOptions::SIGNER: + socket_option_value = signer_; + return SOCKET_OPTION_GET; + + default: + return SOCKET_OPTION_NOT_GET; + } + } + + int getSocketOption(int socket_option_key, std::shared_ptr<auth::Verifier> &socket_option_value) { switch (socket_option_key) { case GeneralTransportOptions::VERIFIER: @@ -827,8 +875,8 @@ class ConsumerSocket : public Socket { int rate_estimation_choice_; // Verification parameters - uint32_t unverified_interval_; - double unverified_ratio_; + uint32_t manifest_factor_relevant_; + uint32_t manifest_factor_alert_; std::shared_ptr<auth::Verifier> verifier_; transport::auth::KeyId *key_id_; std::atomic_bool verify_signature_; @@ -856,6 +904,8 @@ class ConsumerSocket : public Socket { // RTC protocol RtcTransportRecoveryStrategies recovery_strategy_; bool aggregated_data_; + bool content_sharing_mode_; + bool aggregated_interests_; utils::SpinLock guard_raaqm_params_; std::string output_interface_; diff --git a/libtransport/src/implementation/socket_producer.h b/libtransport/src/implementation/socket_producer.h index 37151d497..53ce28766 100644 --- a/libtransport/src/implementation/socket_producer.h +++ b/libtransport/src/implementation/socket_producer.h @@ -51,9 +51,8 @@ class ProducerSocket : public Socket { data_packet_size_(default_values::content_object_packet_size), max_segment_size_(default_values::content_object_packet_size), content_object_expiry_time_(default_values::content_object_expiry_time), - making_manifest_(default_values::manifest_capacity), + manifest_max_capacity_(default_values::manifest_max_capacity), hash_algorithm_(auth::CryptoHashType::SHA256), - signer_(std::make_shared<auth::VoidSigner>()), suffix_strategy_(std::make_shared<utils::IncrementalSuffixStrategy>(0)), aggregated_data_(false), fec_setting_(""), @@ -181,8 +180,8 @@ class ProducerSocket : public Socket { } break; - case GeneralTransportOptions::MAKE_MANIFEST: - making_manifest_ = socket_option_value; + case GeneralTransportOptions::MANIFEST_MAX_CAPACITY: + manifest_max_capacity_ = socket_option_value; break; case GeneralTransportOptions::MAX_SEGMENT_SIZE: @@ -433,6 +432,20 @@ class ProducerSocket : public Socket { return SOCKET_OPTION_SET; } + virtual int setSocketOption( + int socket_option_key, + const std::shared_ptr<auth::Verifier> &socket_option_value) { + switch (socket_option_key) { + case GeneralTransportOptions::VERIFIER: + verifier_.reset(); + verifier_ = socket_option_value; + return SOCKET_OPTION_SET; + + default: + return SOCKET_OPTION_NOT_SET; + } + } + int getSocketOption(int socket_option_key, ProducerCallback **socket_option_value) { // Reschedule the function on the io_service to avoid race condition in @@ -456,12 +469,13 @@ class ProducerSocket : public Socket { virtual int getSocketOption(int socket_option_key, uint32_t &socket_option_value) { switch (socket_option_key) { - case GeneralTransportOptions::MAKE_MANIFEST: - socket_option_value = making_manifest_; + case GeneralTransportOptions::MANIFEST_MAX_CAPACITY: + socket_option_value = (uint32_t)manifest_max_capacity_; break; case GeneralTransportOptions::OUTPUT_BUFFER_SIZE: - socket_option_value = production_protocol_->getOutputBufferSize(); + socket_option_value = + (uint32_t)production_protocol_->getOutputBufferSize(); break; case GeneralTransportOptions::DATA_PACKET_SIZE: @@ -636,6 +650,18 @@ class ProducerSocket : public Socket { return SOCKET_OPTION_GET; } + int getSocketOption(int socket_option_key, + std::shared_ptr<auth::Verifier> &socket_option_value) { + switch (socket_option_key) { + case GeneralTransportOptions::VERIFIER: + socket_option_value = verifier_; + return SOCKET_OPTION_GET; + + default: + return SOCKET_OPTION_NOT_GET; + } + } + int getSocketOption(int socket_option_key, std::string &socket_option_value) { switch (socket_option_key) { case GeneralTransportOptions::FEC_TYPE: @@ -736,11 +762,10 @@ class ProducerSocket : public Socket { std::atomic<size_t> max_segment_size_; std::atomic<uint32_t> content_object_expiry_time_; - std::atomic<uint32_t> making_manifest_; + std::atomic<uint32_t> manifest_max_capacity_; std::atomic<auth::CryptoHashType> hash_algorithm_; std::atomic<auth::CryptoSuite> crypto_suite_; utils::SpinLock signer_lock_; - std::shared_ptr<auth::Signer> signer_; std::shared_ptr<utils::SuffixStrategy> suffix_strategy_; std::shared_ptr<protocol::ProductionProtocol> production_protocol_; diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.cc b/libtransport/src/implementation/tls_rtc_socket_producer.cc deleted file mode 100644 index 06d613ef0..000000000 --- a/libtransport/src/implementation/tls_rtc_socket_producer.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <hicn/transport/core/interest.h> -#include <hicn/transport/interfaces/p2psecure_socket_producer.h> -#include <implementation/p2psecure_socket_producer.h> -#include <implementation/tls_rtc_socket_producer.h> -#include <openssl/bio.h> -#include <openssl/rand.h> -#include <openssl/ssl.h> - -namespace transport { -namespace implementation { - -int TLSRTCProducerSocket::read(BIO *b, char *buf, size_t size, - size_t *readbytes) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = TLSRTCProducerSocket::readOld(b, buf, (int)size); - - if (ret <= 0) { - *readbytes = 0; - return ret; - } - - *readbytes = (size_t)ret; - - return 1; -} - -int TLSRTCProducerSocket::readOld(BIO *b, char *buf, int size) { - TLSRTCProducerSocket *socket; - socket = (TLSRTCProducerSocket *)BIO_get_data(b); - - std::unique_lock<std::mutex> lck(socket->mtx_); - if (!socket->something_to_read_) { - (socket->cv_).wait(lck); - } - - utils::MemBuf *membuf = socket->handshake_packet_->next(); - int size_to_read; - - if ((int)membuf->length() > size) { - size_to_read = size; - } else { - size_to_read = membuf->length(); - socket->something_to_read_ = false; - } - - std::memcpy(buf, membuf->data(), size_to_read); - membuf->trimStart(size_to_read); - - return size_to_read; -} - -int TLSRTCProducerSocket::write(BIO *b, const char *buf, size_t size, - size_t *written) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = TLSRTCProducerSocket::writeOld(b, buf, (int)size); - - if (ret <= 0) { - *written = 0; - return ret; - } - - *written = (size_t)ret; - - return 1; -} - -int TLSRTCProducerSocket::writeOld(BIO *b, const char *buf, int num) { - TLSRTCProducerSocket *socket; - socket = (TLSRTCProducerSocket *)BIO_get_data(b); - - if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) { - uint32_t making_manifest = socket->parent_->making_manifest_; - - socket->tls_chunks_--; - socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, - 0U); - socket->parent_->ProducerSocket::produce( - socket->name_, (const uint8_t *)buf, num, socket->tls_chunks_ == 0, 0); - socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, - making_manifest); - socket->first_ = false; - - } else { - std::unique_ptr<utils::MemBuf> mbuf = - utils::MemBuf::copyBuffer(buf, (std::size_t)num, 0, 0); - auto a = mbuf.release(); - - socket->async_thread_.add([socket = socket, a]() { - socket->to_call_oncontentproduced_--; - auto mbuf = std::unique_ptr<utils::MemBuf>(a); - - socket->RTCProducerSocket::produce(std::move(mbuf)); - - ProducerContentCallback on_content_produced_application; - socket->getSocketOption(ProducerCallbacksOptions::CONTENT_PRODUCED, - on_content_produced_application); - - if (socket->to_call_oncontentproduced_ == 0 && - on_content_produced_application) { - on_content_produced_application( - (transport::interface::ProducerSocket &)(*socket->getInterface()), - std::error_code(), 0); - } - }); - } - - return num; -} - -TLSRTCProducerSocket::TLSRTCProducerSocket( - interface::ProducerSocket *producer_socket, P2PSecureProducerSocket *parent, - const Name &handshake_name) - : ProducerSocket(producer_socket), - RTCProducerSocket(producer_socket), - TLSProducerSocket(producer_socket, parent, handshake_name) { - BIO_METHOD *bio_meth = - BIO_meth_new(BIO_TYPE_ACCEPT, "secure rtc producer socket"); - BIO_meth_set_read(bio_meth, TLSRTCProducerSocket::readOld); - BIO_meth_set_write(bio_meth, TLSRTCProducerSocket::writeOld); - BIO_meth_set_ctrl(bio_meth, TLSProducerSocket::ctrl); - BIO *bio = BIO_new(bio_meth); - BIO_set_init(bio, 1); - BIO_set_data(bio, this); - SSL_set_bio(ssl_, bio, bio); -} - -void TLSRTCProducerSocket::accept() { - HandshakeState handshake_state = getHandshakeState(); - - if (handshake_state == UNINITIATED || handshake_state == CLIENT_HELLO) { - tls_chunks_ = 1; - int result = SSL_accept(ssl_); - - if (result != 1) - throw errors::RuntimeException("Unable to perform client handshake"); - } - - DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!"; - - parent_->list_producers.push_front( - std::move(parent_->map_producers[handshake_name_])); - parent_->map_producers.erase(handshake_name_); - - ProducerInterestCallback on_interest_process_decrypted; - getSocketOption(ProducerCallbacksOptions::CACHE_MISS, - on_interest_process_decrypted); - - if (on_interest_process_decrypted) { - Interest inter(std::move(handshake_packet_)); - on_interest_process_decrypted( - (transport::interface::ProducerSocket &)(*getInterface()), inter); - } - - parent_->cv_.notify_one(); -} - -int TLSRTCProducerSocket::async_accept() { - if (!async_thread_.stopped()) { - async_thread_.add([this]() { this->TLSRTCProducerSocket::accept(); }); - } else { - throw errors::RuntimeException( - "Async thread not running, impossible to perform handshake"); - } - - return 1; -} - -void TLSRTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) { - HandshakeState handshake_state = getHandshakeState(); - - if (handshake_state != SERVER_FINISHED) { - throw errors::RuntimeException( - "New handshake on the same P2P secure producer socket not supported"); - } - - size_t buf_size = buffer->length(); - tls_chunks_ = ceil((float)buf_size / (float)SSL3_RT_MAX_PLAIN_LENGTH); - to_call_oncontentproduced_ = tls_chunks_; - - SSL_write(ssl_, buffer->data(), buf_size); - BIO *wbio = SSL_get_wbio(ssl_); - int i = BIO_flush(wbio); - (void)i; // To shut up gcc 5 -} - -} // namespace implementation -} // namespace transport diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.h b/libtransport/src/implementation/tls_rtc_socket_producer.h deleted file mode 100644 index f6dc425e4..000000000 --- a/libtransport/src/implementation/tls_rtc_socket_producer.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <implementation/tls_socket_producer.h> - -namespace transport { -namespace implementation { - -class P2PSecureProducerSocket; - -class TLSRTCProducerSocket : public TLSProducerSocket { - friend class P2PSecureProducerSocket; - - public: - explicit TLSRTCProducerSocket(interface::ProducerSocket *producer_socket, - P2PSecureProducerSocket *parent, - const Name &handshake_name); - - ~TLSRTCProducerSocket() = default; - - uint32_t produceDatagram(const Name &content_name, - std::unique_ptr<utils::MemBuf> &&buffer) override; - - void accept() override; - - int async_accept() override; - - using TLSProducerSocket::onInterest; - using TLSProducerSocket::produce; - - protected: - static int read(BIO *b, char *buf, size_t size, size_t *readbytes); - - static int readOld(BIO *h, char *buf, int size); - - static int write(BIO *b, const char *buf, size_t size, size_t *written); - - static int writeOld(BIO *h, const char *buf, int num); -}; - -} // namespace implementation - -} // end namespace transport diff --git a/libtransport/src/implementation/tls_socket_consumer.cc b/libtransport/src/implementation/tls_socket_consumer.cc deleted file mode 100644 index b368c4b88..000000000 --- a/libtransport/src/implementation/tls_socket_consumer.cc +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <implementation/tls_socket_consumer.h> -#include <openssl/bio.h> -#include <openssl/ssl.h> -#include <openssl/tls1.h> - -#include <random> - -namespace transport { -namespace implementation { - -void TLSConsumerSocket::setInterestPayload(interface::ConsumerSocket &c, - const core::Interest &interest) { - Interest &int2 = const_cast<Interest &>(interest); - random_suffix_ = int2.getName().getSuffix(); - - if (payload_ != NULL) int2.appendPayload(std::move(payload_)); -} - -/* Return the number of read bytes in the return param */ -int readOldTLS(BIO *b, char *buf, int size) { - if (size < 0) return size; - - TLSConsumerSocket *socket; - socket = (TLSConsumerSocket *)BIO_get_data(b); - - std::unique_lock<std::mutex> lck(socket->mtx_); - - if (!socket->something_to_read_) { - if (!socket->transport_protocol_->isRunning()) { - socket->network_name_.setSuffix(socket->random_suffix_); - socket->ConsumerSocket::consume(socket->network_name_); - } - - if (!socket->something_to_read_) socket->cv_.wait(lck); - } - - size_t size_to_read, read; - size_t chain_size = socket->head_->length(); - - if (socket->head_->isChained()) - chain_size = socket->head_->computeChainDataLength(); - - if (chain_size > (size_t)size) { - read = size_to_read = (size_t)size; - } else { - read = size_to_read = chain_size; - socket->something_to_read_ = false; - } - - while (size_to_read) { - if (socket->head_->length() < size_to_read) { - std::memcpy(buf, socket->head_->data(), socket->head_->length()); - size_to_read -= socket->head_->length(); - buf += socket->head_->length(); - socket->head_ = socket->head_->pop(); - } else { - std::memcpy(buf, socket->head_->data(), size_to_read); - socket->head_->trimStart(size_to_read); - size_to_read = 0; - } - } - - return (int)read; -} - -/* Return the number of read bytes in readbytes */ -int readTLS(BIO *b, char *buf, size_t size, size_t *readbytes) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = readOldTLS(b, buf, (int)size); - - if (ret <= 0) { - *readbytes = 0; - return ret; - } - - *readbytes = (size_t)ret; - - return 1; -} - -/* Return the number of written bytes in the return param */ -int writeOldTLS(BIO *b, const char *buf, int num) { - TLSConsumerSocket *socket; - socket = (TLSConsumerSocket *)BIO_get_data(b); - - socket->payload_ = utils::MemBuf::copyBuffer(buf, num); - - socket->ConsumerSocket::setSocketOption( - ConsumerCallbacksOptions::INTEREST_OUTPUT, - (ConsumerInterestCallback)std::bind( - &TLSConsumerSocket::setInterestPayload, socket, std::placeholders::_1, - std::placeholders::_2)); - - return num; -} - -/* Return the number of written bytes in written */ -int writeTLS(BIO *b, const char *buf, size_t size, size_t *written) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = writeOldTLS(b, buf, (int)size); - - if (ret <= 0) { - *written = 0; - return ret; - } - - *written = (size_t)ret; - - return 1; -} - -long ctrlTLS(BIO *b, int cmd, long num, void *ptr) { return 1; } - -TLSConsumerSocket::TLSConsumerSocket(interface::ConsumerSocket *consumer_socket, - int protocol, SSL *ssl) - : ConsumerSocket(consumer_socket, protocol), - name_(), - decrypted_content_(), - payload_(), - head_(), - something_to_read_(false), - content_downloaded_(false), - random_suffix_(), - producer_namespace_(), - read_callback_decrypted_(), - mtx_(), - cv_(), - async_downloader_tls_() { - /* Create the (d)TLS state */ - const SSL_METHOD *meth = TLS_client_method(); - ctx_ = SSL_CTX_new(meth); - - int result = - SSL_CTX_set_ciphersuites(ctx_, - "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_" - "SHA256:TLS_AES_128_GCM_SHA256"); - if (result != 1) { - throw errors::RuntimeException( - "Unable to set cipher list on TLS subsystem. Aborting."); - } - - SSL_CTX_set_min_proto_version(ctx_, TLS1_3_VERSION); - SSL_CTX_set_max_proto_version(ctx_, TLS1_3_VERSION); - SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, NULL); - SSL_CTX_set_ssl_version(ctx_, meth); - - ssl_ = ssl; - - BIO_METHOD *bio_meth = - BIO_meth_new(BIO_TYPE_CONNECT, "secure consumer socket"); - BIO_meth_set_read(bio_meth, readOldTLS); - BIO_meth_set_write(bio_meth, writeOldTLS); - BIO_meth_set_ctrl(bio_meth, ctrlTLS); - BIO *bio = BIO_new(bio_meth); - BIO_set_init(bio, 1); - BIO_set_data(bio, this); - SSL_set_bio(ssl_, bio, bio); - - std::default_random_engine generator; - std::uniform_int_distribution<int> distribution( - 1, std::numeric_limits<uint32_t>::max()); - random_suffix_ = 0; - - this->ConsumerSocket::setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, - this); -}; - -/* The producer interface is not owned by the application, so is TLSSocket task - * to deallocate the memory */ -TLSConsumerSocket::~TLSConsumerSocket() { delete consumer_interface_; } - -int TLSConsumerSocket::consume(const Name &name, - std::unique_ptr<utils::MemBuf> &&buffer) { - this->payload_ = std::move(buffer); - - this->ConsumerSocket::setSocketOption( - ConsumerCallbacksOptions::INTEREST_OUTPUT, - (ConsumerInterestCallback)std::bind( - &TLSConsumerSocket::setInterestPayload, this, std::placeholders::_1, - std::placeholders::_2)); - - return consume(name); -} - -int TLSConsumerSocket::consume(const Name &name) { - if (transport_protocol_->isRunning()) { - return CONSUMER_BUSY; - } - - if ((SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) { - throw errors::RuntimeException("Handshake not performed"); - } - - return download_content(name); -} - -int TLSConsumerSocket::download_content(const Name &name) { - network_name_ = name; - network_name_.setSuffix(0); - something_to_read_ = false; - content_downloaded_ = false; - - std::size_t max_buffer_size = read_callback_decrypted_->maxBufferSize(); - std::size_t buffer_size = - read_callback_decrypted_->maxBufferSize() + SSL3_RT_MAX_PLAIN_LENGTH; - decrypted_content_ = utils::MemBuf::createCombined(buffer_size); - int result = -1; - std::size_t size = 0; - - while (!content_downloaded_ || something_to_read_) { - result = SSL_read(this->ssl_, decrypted_content_->writableTail(), - SSL3_RT_MAX_PLAIN_LENGTH); - - /* SSL_read returns the data only if there were SSL3_RT_MAX_PLAIN_LENGTH of - * the data has been fully downloaded */ - - /* ASSERT((result < SSL3_RT_MAX_PLAIN_LENGTH && content_downloaded_) || */ - /* result == SSL3_RT_MAX_PLAIN_LENGTH); */ - - if (result >= 0) { - size += result; - decrypted_content_->append(result); - } else { - throw errors::RuntimeException("Unable to download content"); - } - - if (decrypted_content_->length() >= max_buffer_size) { - if (read_callback_decrypted_->isBufferMovable()) { - /* No need to perform an additional copy. The whole buffer will be - * tranferred to the application. */ - read_callback_decrypted_->readBufferAvailable( - std::move(decrypted_content_)); - decrypted_content_ = utils::MemBuf::create(buffer_size); - } else { - /* The buffer will be copied into the application-provided buffer */ - uint8_t *buffer; - std::size_t length; - std::size_t total_length = decrypted_content_->length(); - - while (decrypted_content_->length()) { - buffer = nullptr; - length = 0; - read_callback_decrypted_->getReadBuffer(&buffer, &length); - - if (!buffer || !length) { - throw errors::RuntimeException( - "Invalid buffer provided by the application."); - } - - auto to_copy = std::min(decrypted_content_->length(), length); - std::memcpy(buffer, decrypted_content_->data(), to_copy); - decrypted_content_->trimStart(to_copy); - } - - read_callback_decrypted_->readDataAvailable(total_length); - decrypted_content_->clear(); - } - } - } - - read_callback_decrypted_->readSuccess(size); - - return CONSUMER_FINISHED; -} - -void TLSConsumerSocket::registerPrefix(const Prefix &producer_namespace) { - producer_namespace_ = producer_namespace; -} - -int TLSConsumerSocket::setSocketOption(int socket_option_key, - ReadCallback *socket_option_value) { - return rescheduleOnIOService( - socket_option_key, socket_option_value, - [this](int socket_option_key, ReadCallback *socket_option_value) -> int { - switch (socket_option_key) { - case ConsumerCallbacksOptions::READ_CALLBACK: - read_callback_decrypted_ = socket_option_value; - break; - default: - return SOCKET_OPTION_NOT_SET; - } - - return SOCKET_OPTION_SET; - }); -} - -void TLSConsumerSocket::getReadBuffer(uint8_t **application_buffer, - size_t *max_length) {} - -void TLSConsumerSocket::readDataAvailable(size_t length) noexcept {} - -size_t TLSConsumerSocket::maxBufferSize() const { - return SSL3_RT_MAX_PLAIN_LENGTH; -} - -void TLSConsumerSocket::readBufferAvailable( - std::unique_ptr<utils::MemBuf> &&buffer) noexcept { - std::unique_lock<std::mutex> lck(this->mtx_); - - if (head_) { - head_->prependChain(std::move(buffer)); - } else { - head_ = std::move(buffer); - } - - something_to_read_ = true; - cv_.notify_one(); -} - -void TLSConsumerSocket::readError(const std::error_code &ec) noexcept {} - -void TLSConsumerSocket::readSuccess(std::size_t total_size) noexcept { - std::unique_lock<std::mutex> lck(this->mtx_); - content_downloaded_ = true; - something_to_read_ = true; - cv_.notify_one(); -} - -bool TLSConsumerSocket::isBufferMovable() noexcept { return true; } - -} // namespace implementation -} // namespace transport diff --git a/libtransport/src/implementation/tls_socket_consumer.h b/libtransport/src/implementation/tls_socket_consumer.h deleted file mode 100644 index a74f1ee10..000000000 --- a/libtransport/src/implementation/tls_socket_consumer.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <hicn/transport/interfaces/socket_consumer.h> -#include <implementation/socket_consumer.h> -#include <openssl/ssl.h> - -namespace transport { -namespace implementation { - -class TLSConsumerSocket : public ConsumerSocket, - public interface::ConsumerSocket::ReadCallback { - /* Return the number of read bytes in readbytes */ - friend int readTLS(BIO *b, char *buf, size_t size, size_t *readbytes); - - /* Return the number of read bytes in the return param */ - friend int readOldTLS(BIO *h, char *buf, int size); - - /* Return the number of written bytes in written */ - friend int writeTLS(BIO *b, const char *buf, size_t size, size_t *written); - - /* Return the number of written bytes in the return param */ - friend int writeOldTLS(BIO *h, const char *buf, int num); - - friend long ctrlTLS(BIO *b, int cmd, long num, void *ptr); - - public: - explicit TLSConsumerSocket(interface::ConsumerSocket *consumer_socket, - int protocol, SSL *ssl_); - - ~TLSConsumerSocket(); - - int consume(const Name &name, std::unique_ptr<utils::MemBuf> &&buffer); - int consume(const Name &name) override; - - void registerPrefix(const Prefix &producer_namespace); - - int setSocketOption( - int socket_option_key, - interface::ConsumerSocket::ReadCallback *socket_option_value) override; - - using ConsumerSocket::getSocketOption; - using ConsumerSocket::setSocketOption; - - protected: - /* Callback invoked once an interest has been received and its payload - * decrypted */ - ConsumerInterestCallback on_interest_input_decrypted_; - ConsumerInterestCallback on_interest_process_decrypted_; - - private: - Name name_; - /* SSL handle */ - SSL *ssl_; - SSL_CTX *ctx_; - /* Chain of MemBuf to be used as a temporary buffer to pass descypted data - * from the underlying layer to the application */ - std::unique_ptr<utils::MemBuf> decrypted_content_; - /* Chain of MemBuf holding the payload to be written into interest or data */ - std::unique_ptr<utils::MemBuf> payload_; - /* Chain of MemBuf holding the data retrieved from the underlying layer */ - std::unique_ptr<utils::MemBuf> head_; - bool something_to_read_; - bool content_downloaded_; - uint32_t random_suffix_; - Prefix producer_namespace_; - interface::ConsumerSocket::ReadCallback *read_callback_decrypted_; - std::mutex mtx_; - /* Condition variable for the wait */ - std::condition_variable cv_; - utils::EventThread async_downloader_tls_; - - void setInterestPayload(interface::ConsumerSocket &c, - const core::Interest &interest); - - virtual void getReadBuffer(uint8_t **application_buffer, - size_t *max_length) override; - - virtual void readDataAvailable(size_t length) noexcept override; - - virtual size_t maxBufferSize() const override; - - virtual void readBufferAvailable( - std::unique_ptr<utils::MemBuf> &&buffer) noexcept override; - - virtual void readError(const std::error_code &ec) noexcept override; - - virtual void readSuccess(std::size_t total_size) noexcept override; - - virtual bool isBufferMovable() noexcept override; - - int download_content(const Name &name); -}; - -} // namespace implementation -} // end namespace transport diff --git a/libtransport/src/implementation/tls_socket_producer.cc b/libtransport/src/implementation/tls_socket_producer.cc deleted file mode 100644 index 47f3b43a6..000000000 --- a/libtransport/src/implementation/tls_socket_producer.cc +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <hicn/transport/interfaces/socket_producer.h> -#include <implementation/p2psecure_socket_producer.h> -#include <implementation/tls_socket_producer.h> -#include <openssl/bio.h> -#include <openssl/rand.h> -#include <openssl/ssl.h> - -namespace transport { -namespace implementation { - -/* Return the number of read bytes in readbytes */ -int TLSProducerSocket::read(BIO *b, char *buf, size_t size, size_t *readbytes) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = TLSProducerSocket::readOld(b, buf, (int)size); - - if (ret <= 0) { - *readbytes = 0; - return ret; - } - - *readbytes = (size_t)ret; - - return 1; -} - -/* Return the number of read bytes in the return param */ -int TLSProducerSocket::readOld(BIO *b, char *buf, int size) { - TLSProducerSocket *socket; - socket = (TLSProducerSocket *)BIO_get_data(b); - - std::unique_lock<std::mutex> lck(socket->mtx_); - - DLOG_IF(INFO, VLOG_IS_ON(4)) << "Start wait on the CV."; - - if (!socket->something_to_read_) { - (socket->cv_).wait(lck); - } - - DLOG_IF(INFO, VLOG_IS_ON(4)) << "CV unlocked."; - - /* Either there already is something to read, or the thread has been waken up. - * We must return the payload in the interest anyway */ - utils::MemBuf *membuf = socket->handshake_packet_->next(); - int size_to_read; - - if ((int)membuf->length() > size) { - size_to_read = size; - } else { - size_to_read = (int)membuf->length(); - socket->something_to_read_ = false; - } - - std::memcpy(buf, membuf->data(), size_to_read); - membuf->trimStart(size_to_read); - - return size_to_read; -} - -/* Return the number of written bytes in written */ -int TLSProducerSocket::write(BIO *b, const char *buf, size_t size, - size_t *written) { - int ret; - - if (size > INT_MAX) size = INT_MAX; - - ret = TLSProducerSocket::writeOld(b, buf, (int)size); - - if (ret <= 0) { - *written = 0; - return ret; - } - - *written = (size_t)ret; - - return 1; -} - -/* Return the number of written bytes in the return param */ -int TLSProducerSocket::writeOld(BIO *b, const char *buf, int num) { - TLSProducerSocket *socket; - socket = (TLSProducerSocket *)BIO_get_data(b); - - if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) { - uint32_t making_manifest = socket->parent_->making_manifest_; - - //! socket->tls_chunks_ corresponds to is_last - socket->tls_chunks_--; - socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, - 0U); - socket->parent_->ProducerSocket::produceStream( - socket->name_, (const uint8_t *)buf, num, socket->tls_chunks_ == 0, - socket->last_segment_); - socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, - making_manifest); - socket->first_ = false; - } else { - socket->still_writing_ = true; - - std::unique_ptr<utils::MemBuf> mbuf = - utils::MemBuf::copyBuffer(buf, (std::size_t)num, 0, 0); - auto a = mbuf.release(); - - socket->async_thread_.add([socket = socket, a]() { - auto mbuf = std::unique_ptr<utils::MemBuf>(a); - - socket->tls_chunks_--; - socket->to_call_oncontentproduced_--; - - socket->last_segment_ += socket->ProducerSocket::produceStream( - socket->name_, std::move(mbuf), socket->tls_chunks_ == 0, - socket->last_segment_); - - ProducerContentCallback *on_content_produced_application; - socket->getSocketOption(ProducerCallbacksOptions::CONTENT_PRODUCED, - &on_content_produced_application); - - if (socket->to_call_oncontentproduced_ == 0 && - on_content_produced_application) { - on_content_produced_application->operator()(*socket->getInterface(), - std::error_code(), 0); - } - }); - } - - return num; -} - -TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket, - P2PSecureProducerSocket *parent, - const Name &handshake_name) - : ProducerSocket(producer_socket, - ProductionProtocolAlgorithms::BYTE_STREAM), - on_content_produced_application_(), - mtx_(), - cv_(), - something_to_read_(false), - handshake_state_(UNINITIATED), - name_(), - handshake_packet_(), - last_segment_(0), - parent_(parent), - first_(true), - handshake_name_(handshake_name), - tls_chunks_(0), - to_call_oncontentproduced_(0), - still_writing_(false), - encryption_thread_() { - const SSL_METHOD *meth = TLS_server_method(); - ctx_ = SSL_CTX_new(meth); - - /* Setup SSL context (identity and parameter to use TLS 1.3) */ - SSL_CTX_use_certificate(ctx_, parent->cert_509_); - SSL_CTX_use_PrivateKey(ctx_, parent->pkey_rsa_); - - int result = - SSL_CTX_set_ciphersuites(ctx_, - "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_" - "SHA256:TLS_AES_128_GCM_SHA256"); - - if (result != 1) { - throw errors::RuntimeException( - "Unable to set cipher list on TLS subsystem. Aborting."); - } - - // We force it to be TLS 1.3 - SSL_CTX_set_min_proto_version(ctx_, TLS1_3_VERSION); - SSL_CTX_set_max_proto_version(ctx_, TLS1_3_VERSION); - SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, NULL); - SSL_CTX_set_num_tickets(ctx_, 0); - - result = SSL_CTX_add_custom_ext( - ctx_, 100, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, - TLSProducerSocket::addHicnKeyIdCb, TLSProducerSocket::freeHicnKeyIdCb, - this, TLSProducerSocket::parseHicnKeyIdCb, NULL); - - ssl_ = SSL_new(ctx_); - - /* Setup this producer socker as the bio that TLS will use to write and read - * data (in stream mode) */ - BIO_METHOD *bio_meth = - BIO_meth_new(BIO_TYPE_ACCEPT, "secure producer socket"); - BIO_meth_set_read(bio_meth, TLSProducerSocket::readOld); - BIO_meth_set_write(bio_meth, TLSProducerSocket::writeOld); - BIO_meth_set_ctrl(bio_meth, TLSProducerSocket::ctrl); - BIO *bio = BIO_new(bio_meth); - BIO_set_init(bio, 1); - BIO_set_data(bio, this); - SSL_set_bio(ssl_, bio, bio); - - /* Set the callback so that when an interest is received we catch it and we - * decrypt the payload before passing it to the application. */ - this->ProducerSocket::setSocketOption( - ProducerCallbacksOptions::CACHE_MISS, - (ProducerInterestCallback)std::bind(&TLSProducerSocket::cacheMiss, this, - std::placeholders::_1, - std::placeholders::_2)); - - this->ProducerSocket::setSocketOption( - ProducerCallbacksOptions::CONTENT_PRODUCED, - (ProducerContentCallback)bind( - &TLSProducerSocket::onContentProduced, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3)); -} - -/* The producer interface is not owned by the application, so is TLSSocket task - * to deallocate the memory */ -TLSProducerSocket::~TLSProducerSocket() { delete producer_interface_; } - -void TLSProducerSocket::accept() { - HandshakeState handshake_state = getHandshakeState(); - - if (handshake_state == UNINITIATED || handshake_state == CLIENT_HELLO) { - tls_chunks_ = 1; - int result = SSL_accept(ssl_); - - if (result != 1) - throw errors::RuntimeException("Unable to perform client handshake"); - } - - parent_->list_producers.push_front( - std::move(parent_->map_producers[handshake_name_])); - parent_->map_producers.erase(handshake_name_); - - ProducerInterestCallback *on_interest_process_decrypted; - getSocketOption(ProducerCallbacksOptions::CACHE_MISS, - &on_interest_process_decrypted); - - if (*on_interest_process_decrypted) { - Interest inter(std::move(*handshake_packet_)); - handshake_packet_.reset(); - on_interest_process_decrypted->operator()(*getInterface(), inter); - } else { - throw errors::RuntimeException( - "On interest process unset: unable to perform handshake"); - } - - handshake_state_ = SERVER_FINISHED; - DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!"; -} - -int TLSProducerSocket::async_accept() { - if (!async_thread_.stopped()) { - async_thread_.add([this]() { this->accept(); }); - } else { - throw errors::RuntimeException( - "Async thread not running: unable to perform handshake"); - } - - return 1; -} - -void TLSProducerSocket::onInterest(ProducerSocket &p, Interest &interest) { - HandshakeState handshake_state = getHandshakeState(); - - if (handshake_state == UNINITIATED || handshake_state == CLIENT_HELLO) { - std::unique_lock<std::mutex> lck(mtx_); - - name_ = interest.getName(); - // interest.separateHeaderPayload(); - handshake_packet_ = interest.acquireMemBufReference(); - something_to_read_ = true; - - cv_.notify_one(); - return; - } else if (handshake_state == SERVER_FINISHED) { - // interest.separateHeaderPayload(); - handshake_packet_ = interest.acquireMemBufReference(); - something_to_read_ = true; - - if (interest.getPayload()->length() > 0) { - SSL_read( - ssl_, - const_cast<unsigned char *>(interest.getPayload()->writableData()), - (int)interest.getPayload()->length()); - } - - ProducerInterestCallback *on_interest_input_decrypted; - getSocketOption(ProducerCallbacksOptions::INTEREST_INPUT, - &on_interest_input_decrypted); - - if (*on_interest_input_decrypted) - (*on_interest_input_decrypted)(*getInterface(), interest); - } -} - -void TLSProducerSocket::cacheMiss(interface::ProducerSocket &p, - Interest &interest) { - HandshakeState handshake_state = getHandshakeState(); - - DLOG_IF(INFO, VLOG_IS_ON(3)) << "On cache miss in TLS socket producer."; - - if (handshake_state == CLIENT_HELLO) { - std::unique_lock<std::mutex> lck(mtx_); - - // interest.separateHeaderPayload(); - handshake_packet_ = interest.acquireMemBufReference(); - something_to_read_ = true; - handshake_state_ = CLIENT_FINISHED; - - cv_.notify_one(); - } else if (handshake_state == SERVER_FINISHED) { - // interest.separateHeaderPayload(); - handshake_packet_ = interest.acquireMemBufReference(); - something_to_read_ = true; - - if (interest.getPayload()->length() > 0) { - SSL_read( - ssl_, - const_cast<unsigned char *>(interest.getPayload()->writableData()), - (int)interest.getPayload()->length()); - } - - if (on_interest_process_decrypted_ != VOID_HANDLER) - on_interest_process_decrypted_(*getInterface(), interest); - } -} - -TLSProducerSocket::HandshakeState TLSProducerSocket::getHandshakeState() { - if (SSL_in_before(ssl_)) { - handshake_state_ = UNINITIATED; - } - - if (SSL_in_init(ssl_) && handshake_state_ == UNINITIATED) { - handshake_state_ = CLIENT_HELLO; - } - - return handshake_state_; -} - -void TLSProducerSocket::onContentProduced(interface::ProducerSocket &p, - const std::error_code &err, - uint64_t bytes_written) {} - -uint32_t TLSProducerSocket::produceStream( - const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer, - bool is_last, uint32_t start_offset) { - if (getHandshakeState() != SERVER_FINISHED) { - throw errors::RuntimeException( - "New handshake on the same P2P secure producer socket not supported"); - } - - size_t buf_size = buffer->length(); - name_ = portal_->getServedNamespaces().begin()->mapName(content_name); - tls_chunks_ = to_call_oncontentproduced_ = - (int)ceil((float)buf_size / (float)SSL3_RT_MAX_PLAIN_LENGTH); - - if (!is_last) { - tls_chunks_++; - } - - last_segment_ = start_offset; - - SSL_write(ssl_, buffer->data(), (int)buf_size); - BIO *wbio = SSL_get_wbio(ssl_); - int i = BIO_flush(wbio); - (void)i; // To shut up gcc 5 - - return 0; -} - -long TLSProducerSocket::ctrl(BIO *b, int cmd, long num, void *ptr) { - if (cmd == BIO_CTRL_FLUSH) { - } - - return 1; -} - -int TLSProducerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, - const unsigned char **out, size_t *outlen, - X509 *x, size_t chainidx, int *al, - void *add_arg) { - TLSProducerSocket *socket = reinterpret_cast<TLSProducerSocket *>(add_arg); - - DLOG_IF(INFO, VLOG_IS_ON(3)) - << "On addHicnKeyIdCb, for the prefix registration."; - - if (ext_type == 100) { - auto &prefix = *socket->parent_->portal_->getServedNamespaces().begin(); - const ip_prefix_t &ip_prefix = prefix.toIpPrefixStruct(); - int inet_family = prefix.getAddressFamily(); - uint16_t prefix_len_bits = prefix.getPrefixLength(); - uint8_t prefix_len_bytes = prefix_len_bits / 8; - uint8_t prefix_len_u32 = prefix_len_bits / 32; - - ip_prefix_t *out_ip = (ip_prefix_t *)malloc(sizeof(ip_prefix_t)); - out_ip->family = inet_family; - out_ip->len = prefix_len_bits + 32; - u8 *out_ip_buf = const_cast<u8 *>( - ip_address_get_buffer(&(out_ip->address), inet_family)); - *out = reinterpret_cast<unsigned char *>(out_ip); - - RAND_bytes((unsigned char *)&socket->key_id_, 4); - - memcpy(out_ip_buf, ip_address_get_buffer(&(ip_prefix.address), inet_family), - prefix_len_bytes); - memcpy((out_ip_buf + prefix_len_bytes), &socket->key_id_, 4); - *outlen = sizeof(ip_prefix_t); - - ip_address_t mask = {}; - ip_address_t keyId_component = {}; - u32 *mask_buf; - u32 *keyId_component_buf; - - switch (inet_family) { - case AF_INET: - mask_buf = &(mask.v4.as_u32); - keyId_component_buf = &(keyId_component.v4.as_u32); - break; - case AF_INET6: - mask_buf = mask.v6.as_u32; - keyId_component_buf = keyId_component.v6.as_u32; - break; - default: - throw errors::RuntimeException("Unknown protocol"); - } - - if (prefix_len_bits > (inet_family == AF_INET6 ? IPV6_ADDR_LEN_BITS - 32 - : IPV4_ADDR_LEN_BITS - 32)) - throw errors::RuntimeException( - "Not enough space in the content name to add key_id"); - - mask_buf[prefix_len_u32] = 0xffffffff; - keyId_component_buf[prefix_len_u32] = socket->key_id_; - socket->last_segment_ = 0; - - socket->on_interest_process_decrypted_ = - socket->parent_->on_interest_process_decrypted_; - - socket->registerPrefix( - Prefix(prefix.getName(Name(inet_family, (uint8_t *)&mask), - Name(inet_family, (uint8_t *)&keyId_component), - prefix.getName()), - out_ip->len)); - socket->connect(); - } - return 1; -} - -void TLSProducerSocket::freeHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, - const unsigned char *out, - void *add_arg) { - free(const_cast<unsigned char *>(out)); -} - -int TLSProducerSocket::parseHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, - const unsigned char *in, size_t inlen, - X509 *x, size_t chainidx, int *al, - void *add_arg) { - return 1; -} - -int TLSProducerSocket::setSocketOption( - int socket_option_key, ProducerInterestCallback socket_option_value) { - return rescheduleOnIOService( - socket_option_key, socket_option_value, - [this](int socket_option_key, - ProducerInterestCallback socket_option_value) -> int { - int result = SOCKET_OPTION_SET; - - switch (socket_option_key) { - case ProducerCallbacksOptions::INTEREST_INPUT: - on_interest_input_decrypted_ = socket_option_value; - break; - - case ProducerCallbacksOptions::INTEREST_DROP: - on_interest_dropped_input_buffer_ = socket_option_value; - break; - - case ProducerCallbacksOptions::INTEREST_PASS: - on_interest_inserted_input_buffer_ = socket_option_value; - break; - - case ProducerCallbacksOptions::CACHE_HIT: - on_interest_satisfied_output_buffer_ = socket_option_value; - break; - - case ProducerCallbacksOptions::CACHE_MISS: - on_interest_process_decrypted_ = socket_option_value; - break; - - default: - result = SOCKET_OPTION_NOT_SET; - break; - } - - return result; - }); -} - -int TLSProducerSocket::setSocketOption( - int socket_option_key, ProducerContentCallback socket_option_value) { - return rescheduleOnIOService( - socket_option_key, socket_option_value, - [this](int socket_option_key, - ProducerContentCallback socket_option_value) -> int { - switch (socket_option_key) { - case ProducerCallbacksOptions::CONTENT_PRODUCED: - on_content_produced_application_ = socket_option_value; - break; - - default: - return SOCKET_OPTION_NOT_SET; - } - - return SOCKET_OPTION_SET; - }); -} - -int TLSProducerSocket::getSocketOption( - int socket_option_key, ProducerContentCallback **socket_option_value) { - return rescheduleOnIOService( - socket_option_key, socket_option_value, - [this](int socket_option_key, - ProducerContentCallback **socket_option_value) -> int { - switch (socket_option_key) { - case ProducerCallbacksOptions::CONTENT_PRODUCED: - *socket_option_value = &on_content_produced_application_; - break; - - default: - return SOCKET_OPTION_NOT_GET; - } - - return SOCKET_OPTION_GET; - }); -} - -} // namespace implementation -} // namespace transport diff --git a/libtransport/src/implementation/tls_socket_producer.h b/libtransport/src/implementation/tls_socket_producer.h deleted file mode 100644 index 0e958b321..000000000 --- a/libtransport/src/implementation/tls_socket_producer.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <implementation/socket_producer.h> -#include <openssl/ssl.h> - -#include <condition_variable> -#include <mutex> - -namespace transport { -namespace implementation { - -class P2PSecureProducerSocket; - -class TLSProducerSocket : virtual public ProducerSocket { - friend class P2PSecureProducerSocket; - - public: - explicit TLSProducerSocket(interface::ProducerSocket *producer_socket, - P2PSecureProducerSocket *parent, - const Name &handshake_name); - - ~TLSProducerSocket(); - - uint32_t produceStream(const Name &content_name, const uint8_t *buffer, - size_t buffer_size, bool is_last = true, - uint32_t start_offset = 0) override { - return produceStream(content_name, - utils::MemBuf::copyBuffer(buffer, buffer_size), - is_last, start_offset); - } - - uint32_t produceStream(const Name &content_name, - std::unique_ptr<utils::MemBuf> &&buffer, - bool is_last = true, - uint32_t start_offset = 0) override; - - virtual void accept(); - - virtual int async_accept(); - - virtual int setSocketOption( - int socket_option_key, - ProducerInterestCallback socket_option_value) override; - - virtual int setSocketOption( - int socket_option_key, - ProducerContentCallback socket_option_value) override; - - virtual int getSocketOption( - int socket_option_key, - ProducerContentCallback **socket_option_value) override; - - int getSocketOption(int socket_option_key, - ProducerContentCallback &socket_option_value); - - int getSocketOption(int socket_option_key, - ProducerInterestCallback &socket_option_value); - - using ProducerSocket::getSocketOption; - // using ProducerSocket::onInterest; - using ProducerSocket::setSocketOption; - - protected: - enum HandshakeState { - UNINITIATED, - CLIENT_HELLO, // when CLIENT_HELLO interest has been received - CLIENT_FINISHED, // when CLIENT_FINISHED interest has been received - SERVER_FINISHED, // when handshake is done - }; - /* Callback invoked once an interest has been received and its payload - * decrypted */ - ProducerInterestCallback on_interest_input_decrypted_; - ProducerInterestCallback on_interest_process_decrypted_; - ProducerContentCallback on_content_produced_application_; - std::mutex mtx_; - /* Condition variable for the wait */ - std::condition_variable cv_; - /* Bool variable, true if there is something to read (an interest arrived) */ - bool something_to_read_; - /* Bool variable, true if CLIENT_FINISHED interest has been received */ - HandshakeState handshake_state_; - /* First interest that open a secure connection */ - transport::core::Name name_; - /* SSL handle */ - SSL *ssl_; - SSL_CTX *ctx_; - Packet::MemBufPtr handshake_packet_; - std::unique_ptr<utils::MemBuf> head_; - std::uint32_t last_segment_; - std::uint32_t key_id_; - std::thread *handshake; - P2PSecureProducerSocket *parent_; - bool first_; - Name handshake_name_; - int tls_chunks_; - int to_call_oncontentproduced_; - bool still_writing_; - utils::EventThread encryption_thread_; - utils::EventThread async_thread_; - - void onInterest(ProducerSocket &p, Interest &interest); - - void cacheMiss(interface::ProducerSocket &p, Interest &interest); - - /* Return the number of read bytes in readbytes */ - static int read(BIO *b, char *buf, size_t size, size_t *readbytes); - - /* Return the number of read bytes in the return param */ - static int readOld(BIO *h, char *buf, int size); - - /* Return the number of written bytes in written */ - static int write(BIO *b, const char *buf, size_t size, size_t *written); - - /* Return the number of written bytes in the return param */ - static int writeOld(BIO *h, const char *buf, int num); - - static long ctrl(BIO *b, int cmd, long num, void *ptr); - - static int addHicnKeyIdCb(SSL *s, unsigned int ext_type, unsigned int context, - const unsigned char **out, size_t *outlen, X509 *x, - size_t chainidx, int *al, void *add_arg); - - static void freeHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, const unsigned char *out, - void *add_arg); - - static int parseHicnKeyIdCb(SSL *s, unsigned int ext_type, - unsigned int context, const unsigned char *in, - size_t inlen, X509 *x, size_t chainidx, int *al, - void *add_arg); - - void onContentProduced(interface::ProducerSocket &p, - const std::error_code &err, uint64_t bytes_written); - - HandshakeState getHandshakeState(); -}; - -} // namespace implementation -} // end namespace transport |