diff --git a/targets/pna_nic/Makefile.am b/targets/pna_nic/Makefile.am index 2ae34b70..2ede5f32 100644 --- a/targets/pna_nic/Makefile.am +++ b/targets/pna_nic/Makefile.am @@ -15,14 +15,15 @@ externs/pna_counter.h externs/pna_counter.cpp \ externs/pna_meter.h externs/pna_meter.cpp \ externs/pna_random.h externs/pna_random.cpp \ externs/pna_internet_checksum.h externs/pna_internet_checksum.cpp \ -externs/pna_hash.h externs/pna_hash.cpp +externs/pna_hash.h externs/pna_hash.cpp \ +externs/pna_ipsec_accelerator.h externs/pna_ipsec_accelerator.cpp libpnanic_la_LIBADD = \ $(top_builddir)/src/bm_sim/libbmsim.la \ $(top_builddir)/src/bf_lpm_trie/libbflpmtrie.la \ $(top_builddir)/src/BMI/libbmi.la \ $(top_builddir)/third_party/jsoncpp/libjson.la \ --lboost_system $(THRIFT_LIB) -lboost_program_options -lboost_filesystem +-lboost_system $(THRIFT_LIB) -lboost_program_options -lboost_filesystem -lcrypto if COND_THRIFT diff --git a/targets/pna_nic/externs/pna_ipsec_accelerator.cpp b/targets/pna_nic/externs/pna_ipsec_accelerator.cpp new file mode 100644 index 00000000..73a51130 --- /dev/null +++ b/targets/pna_nic/externs/pna_ipsec_accelerator.cpp @@ -0,0 +1,138 @@ +/* Copyright 2024 Marvell Technology, Inc. + * + * 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. + */ + +/* + * Rupesh Chiluka (rchiluka@marvell.com) + * + */ + +#include "pna_ipsec_accelerator.h" + +namespace bm { + +namespace pna { + +void PNA_IpsecAccelerator::init() { + _is_enabled = false; +} + +void PNA_IpsecAccelerator::decrypt() { + std::vector raw_packet_data; + raw_packet_data.resize(get_packet().get_data_size(), '\0'); + std::copy(get_packet().data(), + get_packet().data() + get_packet().get_data_size(), + raw_packet_data.begin()); + + // check the ICV + // compute HMAC + // drop the packet if ICV and the computed hmac are not the same + // decrypt + // create IV + // std::vector IV; + unsigned char iv[17] = {0}; + unsigned char key[] = "sixteenbytes key"; + + std::copy_n(raw_packet_data.begin(), 16, iv); + + EVP_CIPHER_CTX *ctx; + + ctx = EVP_CIPHER_CTX_new(); + if (! EVP_DecryptInit_ex2(ctx, EVP_aes_128_cbc(), key, iv, NULL)) { + // Error + EVP_CIPHER_CTX_free(ctx); + return; + } + + EVP_CIPHER_CTX_set_padding(ctx, 0); + + + std::vector encrypted; + encrypted.resize(raw_packet_data.size() - 16, '\0'); + std::copy(raw_packet_data.begin() + 16, raw_packet_data.end(), encrypted.begin()); + + std::vector decrypted; + decrypted.resize(encrypted.size() + 16, '\0'); + + int outlen = 0; + int tmplen = 0; + + if (!EVP_DecryptUpdate(ctx, decrypted.data(), &outlen, encrypted.data(), + encrypted.size())) { + // Error + EVP_CIPHER_CTX_free(ctx); + std::cout << "Error in DecryptUpdate" << std::endl; + return; + } + + if (!EVP_DecryptFinal_ex(ctx, decrypted.data() + outlen, &tmplen)) { + // Error + EVP_CIPHER_CTX_free(ctx); + ERR_print_errors_fp(stderr); + std::cout << "Error in DecryptFinal" << std::endl; + return; + } + + outlen += tmplen; + decrypted.resize(outlen); // resize vector to actual output length + EVP_CIPHER_CTX_free(ctx); + + // padding length + int padding_length = *(decrypted.data() + encrypted.size() - 2); + + // payload + std::vector payload; + payload.resize(decrypted.size() - 2 - padding_length, '\0'); + std::copy(decrypted.begin(), decrypted.end() - 2 - padding_length, payload.begin()); + + // replace payload + // first, remove all the data + get_packet().remove(get_packet().get_data_size()); + // make room for the ciphertext and write the ciphertext in it + char *payload_start = get_packet().prepend( + (size_t) decrypted.size() - 2 - padding_length); + // 2 = padding length + next header + for (uint i =0; i < (size_t) decrypted.size() - 2 - padding_length; i++) { + payload_start[i] = payload[i]; + } +} + +void PNA_IpsecAccelerator::encrypt() { +} + +void PNA_IpsecAccelerator::set_sa_index(const Data &sa_index) { + _sa_index = sa_index.get(); +} + +void PNA_IpsecAccelerator::enable() { + _is_enabled = true; + decrypt(); +} + +void PNA_IpsecAccelerator::disable() { + _is_enabled = false; +} + +BM_REGISTER_EXTERN_W_NAME(ipsec_accelerator, PNA_IpsecAccelerator); +BM_REGISTER_EXTERN_W_NAME_METHOD(ipsec_accelerator, PNA_IpsecAccelerator, set_sa_index, const Data &); +BM_REGISTER_EXTERN_W_NAME_METHOD(ipsec_accelerator, PNA_IpsecAccelerator, enable); +BM_REGISTER_EXTERN_W_NAME_METHOD(ipsec_accelerator, PNA_IpsecAccelerator, disable); + +} // namespace bm::pna + +} // namespace bm + +int import_ipsec_accelerator() { + return 0; +} diff --git a/targets/pna_nic/externs/pna_ipsec_accelerator.h b/targets/pna_nic/externs/pna_ipsec_accelerator.h new file mode 100644 index 00000000..c5ffc7ae --- /dev/null +++ b/targets/pna_nic/externs/pna_ipsec_accelerator.h @@ -0,0 +1,61 @@ +/* Copyright 2024 Marvell Technology, Inc. + * + * 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. + */ + +/* + * Rupesh Chiluka (rchiluka@marvell.com) + * + */ + + +#ifndef PNA_NIC_PNA_IPSECACCELERATOR_H_ +#define PNA_NIC_PNA_IPSECACCELERATOR_H_ + +#include +#include +#include +#include + +namespace bm { + +namespace pna { + +class PNA_IpsecAccelerator : public bm::ExternType { + public: + + BM_EXTERN_ATTRIBUTES { + } + + void init() override; + + void set_sa_index(const Data &sa_index); + + void enable(); + + void disable(); + + void decrypt(); + + void encrypt(); + + private: + uint32_t _sa_index; + bool _is_enabled = false; +}; + +} // namespace bm::pna + +} // namespace bm + +#endif // PNA_NIC_PNA_IPSECACCELERATOR_H_ diff --git a/targets/pna_nic/pna_nic.cpp b/targets/pna_nic/pna_nic.cpp index 76aaa396..82d05c0f 100644 --- a/targets/pna_nic/pna_nic.cpp +++ b/targets/pna_nic/pna_nic.cpp @@ -36,6 +36,7 @@ extern int import_meters(); extern int import_random(); extern int import_internet_checksum(); extern int import_hash(); +extern int import_ipsec_accelerator(); namespace bm { @@ -78,6 +79,7 @@ PnaNic::PnaNic(bool enable_swap) import_random(); import_internet_checksum(); import_hash(); + import_ipsec_accelerator(); } #define PACKET_LENGTH_REG_IDX 0 @@ -204,6 +206,21 @@ PnaNic::main_thread() { Deparser *deparser = this->get_deparser("main_deparser"); deparser->deparse(packet.get()); + + // recirculation + if ((port_t) packet->get_egress_port() == PNA_PORT_RECIRCULATE) { + BMLOG_DEBUG_PKT(*packet, "Recirculating packet"); + + phv->reset(); + phv->reset_header_stacks(); + phv->reset_metadata(); + + phv->get_field("pna_main_parser_input_metadata.recirculated") + .set(1); + input_buffer.push_front(std::move(packet)); + continue; + } + output_buffer.push_front(std::move(packet)); } } diff --git a/targets/pna_nic/pna_nic.h b/targets/pna_nic/pna_nic.h index c929f638..e1e17a74 100644 --- a/targets/pna_nic/pna_nic.h +++ b/targets/pna_nic/pna_nic.h @@ -79,6 +79,7 @@ class PnaNic : public Switch { private: static packet_id_t packet_id; + static constexpr port_t PNA_PORT_RECIRCULATE = 0xfffffffa; enum PktInstanceType { FROM_NET_PORT,