|
| 1 | +/* |
| 2 | + * |
| 3 | + * Copyright 2021-2024 Software Radio Systems Limited |
| 4 | + * |
| 5 | + * By using this file, you agree to the terms and conditions set |
| 6 | + * forth in the LICENSE file which can be found at the top level of |
| 7 | + * the distribution. |
| 8 | + * |
| 9 | + */ |
| 10 | + |
| 11 | +#include "lib/security/integrity_engine_generic.h" |
| 12 | +#include "nia1_test_set.h" |
| 13 | +#include "nia2_test_set.h" |
| 14 | +#include "nia3_test_set.h" |
| 15 | +#include "srsran/security/integrity_engine.h" |
| 16 | +#include "srsran/security/security.h" |
| 17 | +#include "srsran/srslog/srslog.h" |
| 18 | +#include <gtest/gtest.h> |
| 19 | + |
| 20 | +using namespace srsran; |
| 21 | +using namespace srsran::security; |
| 22 | + |
| 23 | +/// Fixture class for integrity engine tests |
| 24 | +class fxt_base : public testing::TestWithParam<nia_test_set> |
| 25 | +{ |
| 26 | +protected: |
| 27 | + void SetUp() override |
| 28 | + { |
| 29 | + // init test's logger |
| 30 | + srslog::init(); |
| 31 | + logger.set_level(srslog::basic_levels::debug); |
| 32 | + logger.set_hex_dump_max_size(3000); |
| 33 | + |
| 34 | + // init SEC logger |
| 35 | + srslog::fetch_basic_logger("SEC", false).set_level(srslog::basic_levels::debug); |
| 36 | + srslog::fetch_basic_logger("SEC", false).set_hex_dump_max_size(-1); |
| 37 | + |
| 38 | + logger.info("Created fixture for integrity engine test"); |
| 39 | + } |
| 40 | + |
| 41 | + void TearDown() override |
| 42 | + { |
| 43 | + // flush logger after each test |
| 44 | + srslog::flush(); |
| 45 | + } |
| 46 | + |
| 47 | + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); |
| 48 | +}; |
| 49 | + |
| 50 | +/// Fixture class for integrity engine tests with NIA1 |
| 51 | +class fxt_nia1 : public fxt_base |
| 52 | +{}; |
| 53 | + |
| 54 | +/// Fixture class for integrity engine tests with NIA2 |
| 55 | +class fxt_nia2 : public fxt_base |
| 56 | +{}; |
| 57 | + |
| 58 | +/// Fixture class for integrity engine tests with NIA3 |
| 59 | +class fxt_nia3 : public fxt_base |
| 60 | +{}; |
| 61 | + |
| 62 | +/// Converts a hex string (e.g. 01FA02) to a sec_as_key. |
| 63 | +sec_key make_sec_key(const std::string& hex_str) |
| 64 | +{ |
| 65 | + byte_buffer key_buf = make_byte_buffer(hex_str).value(); |
| 66 | + sec_key key = {}; |
| 67 | + std::copy(key_buf.begin(), key_buf.end(), key.begin()); |
| 68 | + return key; |
| 69 | +} |
| 70 | + |
| 71 | +/// Converts a hex string (e.g. 01FA02) to a sec_128_as_key. |
| 72 | +sec_128_key make_sec_128_key(const std::string& hex_str) |
| 73 | +{ |
| 74 | + byte_buffer key_buf = make_byte_buffer(hex_str).value(); |
| 75 | + sec_128_key key = {}; |
| 76 | + std::copy(key_buf.begin(), key_buf.end(), key.begin()); |
| 77 | + return key; |
| 78 | +} |
| 79 | + |
| 80 | +/// Compares two byte arrays |
| 81 | +int arrcmp(uint8_t const* const a, uint8_t const* const b, uint32_t len) |
| 82 | +{ |
| 83 | + uint32_t i = 0; |
| 84 | + |
| 85 | + for (i = 0; i < len; i++) { |
| 86 | + if (a[i] != b[i]) { |
| 87 | + return a[i] - b[i]; |
| 88 | + } |
| 89 | + } |
| 90 | + return 0; |
| 91 | +} |
| 92 | + |
| 93 | +bool trim_tail_to_bitlength(byte_buffer_view buf, uint32_t bitlength) |
| 94 | +{ |
| 95 | + if ((bitlength + 7) / 8 != buf.length()) { |
| 96 | + return false; |
| 97 | + } |
| 98 | + uint32_t padding = bitlength % 8; |
| 99 | + if (padding > 0) { |
| 100 | + uint8_t mask = 0xff << (8 - padding); |
| 101 | + buf[buf.length() - 1] &= mask; |
| 102 | + } |
| 103 | + return true; |
| 104 | +} |
| 105 | + |
| 106 | +TEST_P(fxt_nia1, integrity_engine_generic_nia1) |
| 107 | +{ |
| 108 | + nia_test_set param = GetParam(); |
| 109 | + |
| 110 | + // Pack hex strings into srsran types |
| 111 | + sec_128_key key = make_sec_128_key(param.ik_cstr); |
| 112 | + auto dir = static_cast<security_direction>(param.direction); |
| 113 | + byte_buffer message = make_byte_buffer(param.message_cstr).value(); |
| 114 | + byte_buffer mact_buf = make_byte_buffer(param.mact_cstr).value(); |
| 115 | + byte_buffer prot_buf = message.deep_copy().value(); |
| 116 | + ASSERT_TRUE(prot_buf.append(mact_buf)); |
| 117 | + |
| 118 | + // Create integrity engine |
| 119 | + std::unique_ptr<integrity_engine> nia = |
| 120 | + std::make_unique<integrity_engine_generic>(key, param.bearer, dir, integrity_algorithm::nia1); |
| 121 | + |
| 122 | + // Apply integrity and compare results |
| 123 | + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); |
| 124 | + ASSERT_TRUE(result.buf.has_value()); |
| 125 | + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); |
| 126 | + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); |
| 127 | + EXPECT_EQ(result.buf.value(), prot_buf); |
| 128 | +} |
| 129 | + |
| 130 | +TEST_P(fxt_nia2, integrity_engine_generic_nia2) |
| 131 | +{ |
| 132 | + nia_test_set param = GetParam(); |
| 133 | + |
| 134 | + // Pack hex strings into srsran types |
| 135 | + sec_128_key key = make_sec_128_key(param.ik_cstr); |
| 136 | + auto dir = static_cast<security_direction>(param.direction); |
| 137 | + byte_buffer message = make_byte_buffer(param.message_cstr).value(); |
| 138 | + byte_buffer mact_buf = make_byte_buffer(param.mact_cstr).value(); |
| 139 | + byte_buffer prot_buf = message.deep_copy().value(); |
| 140 | + ASSERT_TRUE(prot_buf.append(mact_buf)); |
| 141 | + |
| 142 | + // Create integrity engine |
| 143 | + std::unique_ptr<integrity_engine> nia = |
| 144 | + std::make_unique<integrity_engine_generic>(key, param.bearer, dir, integrity_algorithm::nia2); |
| 145 | + |
| 146 | + // Apply integrity and compare results |
| 147 | + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); |
| 148 | + ASSERT_TRUE(result.buf.has_value()); |
| 149 | + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); |
| 150 | + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); |
| 151 | + EXPECT_EQ(result.buf.value(), prot_buf); |
| 152 | +} |
| 153 | + |
| 154 | +TEST_P(fxt_nia3, integrity_engine_generic_nia3) |
| 155 | +{ |
| 156 | + nia_test_set param = GetParam(); |
| 157 | + |
| 158 | + // Pack hex strings into srsran types |
| 159 | + sec_128_key key = make_sec_128_key(param.ik_cstr); |
| 160 | + auto dir = static_cast<security_direction>(param.direction); |
| 161 | + byte_buffer message = make_byte_buffer(param.message_cstr).value(); |
| 162 | + byte_buffer mact_buf = make_byte_buffer(param.mact_cstr).value(); |
| 163 | + byte_buffer prot_buf = message.deep_copy().value(); |
| 164 | + ASSERT_TRUE(prot_buf.append(mact_buf)); |
| 165 | + |
| 166 | + // Create integrity engine |
| 167 | + std::unique_ptr<integrity_engine> nia = |
| 168 | + std::make_unique<integrity_engine_generic>(key, param.bearer, dir, integrity_algorithm::nia3); |
| 169 | + |
| 170 | + // Apply integrity and compare results |
| 171 | + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); |
| 172 | + ASSERT_TRUE(result.buf.has_value()); |
| 173 | + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); |
| 174 | + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); |
| 175 | + EXPECT_EQ(result.buf.value(), prot_buf); |
| 176 | +} |
| 177 | + |
| 178 | +////////////////////////////////////////////////////////// |
| 179 | +// Finally, instantiate all testcases for each test set // |
| 180 | +////////////////////////////////////////////////////////// |
| 181 | +std::string test_param_info_to_string(const ::testing::TestParamInfo<nia_test_set>& info) |
| 182 | +{ |
| 183 | + fmt::memory_buffer buffer; |
| 184 | + fmt::format_to(buffer, "{}", info.param.name); |
| 185 | + return fmt::to_string(buffer); |
| 186 | +} |
| 187 | + |
| 188 | +INSTANTIATE_TEST_SUITE_P(nia1, |
| 189 | + fxt_nia1, |
| 190 | + ::testing::ValuesIn(nia1_test_set.begin(), nia1_test_set.end()), |
| 191 | + test_param_info_to_string); |
| 192 | + |
| 193 | +INSTANTIATE_TEST_SUITE_P(nia2, |
| 194 | + fxt_nia2, |
| 195 | + ::testing::ValuesIn(nia2_test_set.begin(), nia2_test_set.end()), |
| 196 | + test_param_info_to_string); |
| 197 | + |
| 198 | +INSTANTIATE_TEST_SUITE_P(nia3, |
| 199 | + fxt_nia3, |
| 200 | + ::testing::ValuesIn(nia3_test_set.begin(), nia3_test_set.end()), |
| 201 | + test_param_info_to_string); |
| 202 | + |
| 203 | +int main(int argc, char** argv) |
| 204 | +{ |
| 205 | + srslog::init(); |
| 206 | + ::testing::InitGoogleTest(&argc, argv); |
| 207 | + return RUN_ALL_TESTS(); |
| 208 | +} |
0 commit comments