|
| 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/ciphering_engine_nea2.h" |
| 12 | +#include "srsran/security/ciphering_engine.h" |
| 13 | +#include "srsran/security/security.h" |
| 14 | +#include "srsran/srslog/srslog.h" |
| 15 | +#include <gtest/gtest.h> |
| 16 | + |
| 17 | +using namespace srsran; |
| 18 | +using namespace srsran::security; |
| 19 | + |
| 20 | +/// Fixture class for ciphering engine tests |
| 21 | +class ciphering_engine_test : public ::testing::Test |
| 22 | +{ |
| 23 | +protected: |
| 24 | + void SetUp() override |
| 25 | + { |
| 26 | + // init test's logger |
| 27 | + srslog::init(); |
| 28 | + logger.set_level(srslog::basic_levels::debug); |
| 29 | + |
| 30 | + // init SEC logger |
| 31 | + srslog::fetch_basic_logger("SEC", false).set_level(srslog::basic_levels::debug); |
| 32 | + srslog::fetch_basic_logger("SEC", false).set_hex_dump_max_size(-1); |
| 33 | + |
| 34 | + logger.info("Created fixture for ciphering engine test"); |
| 35 | + } |
| 36 | + |
| 37 | + void TearDown() override |
| 38 | + { |
| 39 | + // flush logger after each test |
| 40 | + srslog::flush(); |
| 41 | + } |
| 42 | + |
| 43 | + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); |
| 44 | +}; |
| 45 | + |
| 46 | +/// Converts a hex string (e.g. 01FA02) to a sec_as_key. |
| 47 | +sec_key make_sec_key(const std::string& hex_str) |
| 48 | +{ |
| 49 | + byte_buffer key_buf = make_byte_buffer(hex_str).value(); |
| 50 | + sec_key key = {}; |
| 51 | + std::copy(key_buf.begin(), key_buf.end(), key.begin()); |
| 52 | + return key; |
| 53 | +} |
| 54 | + |
| 55 | +/// Converts a hex string (e.g. 01FA02) to a sec_128_as_key. |
| 56 | +sec_128_key make_sec_128_key(const std::string& hex_str) |
| 57 | +{ |
| 58 | + byte_buffer key_buf = make_byte_buffer(hex_str).value(); |
| 59 | + sec_128_key key = {}; |
| 60 | + std::copy(key_buf.begin(), key_buf.end(), key.begin()); |
| 61 | + return key; |
| 62 | +} |
| 63 | + |
| 64 | +/// Compares two byte arrays |
| 65 | +int arrcmp(uint8_t const* const a, uint8_t const* const b, uint32_t len) |
| 66 | +{ |
| 67 | + uint32_t i = 0; |
| 68 | + |
| 69 | + for (i = 0; i < len; i++) { |
| 70 | + if (a[i] != b[i]) { |
| 71 | + return a[i] - b[i]; |
| 72 | + } |
| 73 | + } |
| 74 | + return 0; |
| 75 | +} |
| 76 | + |
| 77 | +/// 128-NEA2 Test Set 1 |
| 78 | +/// Ref: TS 33.501 Sec. D.4.4, TS 33.401 Sec. C.1 128-EEA2 |
| 79 | +TEST_F(ciphering_engine_test, security_nea2_testset1) |
| 80 | +{ |
| 81 | + // Testdata in plain format |
| 82 | + const char* key_cstr = "d3c5d592327fb11c4035c6680af8c6d1"; |
| 83 | + uint32_t count = 0x398a59b4; |
| 84 | + uint8_t bearer = 0x15; |
| 85 | + uint8_t direction = 1; |
| 86 | + // uint32_t length = 253; |
| 87 | + const char* plaintext_cstr = "981ba6824c1bfb1ab485472029b71d808ce33e2cc3c0b5fc1f3de8a6dc66b1f0"; |
| 88 | + const char* ciphertext_cstr = "e9fed8a63d155304d71df20bf3e82214b20ed7dad2f233dc3c22d7bdeeed8e78"; |
| 89 | + |
| 90 | + // Pack hex strings into srsran types |
| 91 | + sec_128_key key = make_sec_128_key(key_cstr); |
| 92 | + security_direction dir = static_cast<security_direction>(direction); |
| 93 | + byte_buffer plaintext = make_byte_buffer(plaintext_cstr).value(); |
| 94 | + byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr).value(); |
| 95 | + |
| 96 | + // Create ciphering engine |
| 97 | + std::unique_ptr<ciphering_engine> nea = std::make_unique<ciphering_engine_nea2>(key, bearer, dir); |
| 98 | + |
| 99 | + // Apply ciphering and compare results |
| 100 | + security_result result = nea->apply_ciphering(plaintext.deep_copy().value(), 0, count); |
| 101 | + ASSERT_TRUE(result.buf.has_value()); |
| 102 | + EXPECT_EQ(result.buf.value(), ciphertext); |
| 103 | +} |
| 104 | + |
| 105 | +/// 128-NEA2 Test Set 2 |
| 106 | +/// Ref: TS 33.501 Sec. D.4.4, TS 33.401 Sec. C.1 128-EEA2 |
| 107 | +TEST_F(ciphering_engine_test, security_nea2_testset2) |
| 108 | +{ |
| 109 | + // Testdata in plain format |
| 110 | + const char* key_cstr = "2bd6459f82c440e0952c49104805ff48"; |
| 111 | + uint32_t count = 0xc675a64b; |
| 112 | + uint8_t bearer = 0x0c; |
| 113 | + uint8_t direction = 1; |
| 114 | + // uint32_t length = 798; |
| 115 | + const char* plaintext_cstr = |
| 116 | + "7ec61272743bf1614726446a6c38ced166f6ca76eb5430044286346cef130f92922b03450d3a9975e5bd2ea0eb55ad8e1b199e3ec4316020" |
| 117 | + "e9a1b285e762795359b7bdfd39bef4b2484583d5afe082aee638bf5fd5a606193901a08f4ab41aab9b134880"; |
| 118 | + const char* ciphertext_cstr = |
| 119 | + "5961605353c64bdca15b195e288553a910632506d6200aa790c4c806c99904cf2445cc50bb1cf168a49673734e081b57e324ce5259c0e78d" |
| 120 | + "4cd97b870976503c0943f2cb5ae8f052c7b7d392239587b8956086bcab18836042e2e6ce42432a17105c53d0"; |
| 121 | + |
| 122 | + // Pack hex strings into srsran types |
| 123 | + sec_128_key key = make_sec_128_key(key_cstr); |
| 124 | + security_direction dir = static_cast<security_direction>(direction); |
| 125 | + byte_buffer plaintext = make_byte_buffer(plaintext_cstr).value(); |
| 126 | + byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr).value(); |
| 127 | + |
| 128 | + // Create ciphering engine |
| 129 | + std::unique_ptr<ciphering_engine> nea = std::make_unique<ciphering_engine_nea2>(key, bearer, dir); |
| 130 | + |
| 131 | + // Apply ciphering and compare results |
| 132 | + security_result result = nea->apply_ciphering(plaintext.deep_copy().value(), 0, count); |
| 133 | + ASSERT_TRUE(result.buf.has_value()); |
| 134 | + EXPECT_EQ(result.buf.value(), ciphertext); |
| 135 | +} |
| 136 | + |
| 137 | +/// 128-NEA2 Test Set 3 |
| 138 | +/// Ref: TS 33.501 Sec. D.4.4, TS 33.401 Sec. C.1 128-EEA2 |
| 139 | +TEST_F(ciphering_engine_test, security_nea2_testset3) |
| 140 | +{ |
| 141 | + // Testdata in plain format |
| 142 | + const char* key_cstr = "0a8b6bd8d9b08b08d64e32d1817777fb"; |
| 143 | + uint32_t count = 0x544d49cd; |
| 144 | + uint8_t bearer = 0x04; |
| 145 | + uint8_t direction = 0; |
| 146 | + // uint32_t length = 310; |
| 147 | + const char* plaintext_cstr = "fd40a41d370a1f65745095687d47ba1d36d2349e23f644392c8ea9c49d40c13271aff264d0f248"; |
| 148 | + const char* ciphertext_cstr = "75750d37b4bba2a4dedb34235bd68c6645acdaaca48138a3b0c471e2a7041a576423d2927287f0"; |
| 149 | + |
| 150 | + // Pack hex strings into srsran types |
| 151 | + sec_128_key key = make_sec_128_key(key_cstr); |
| 152 | + security_direction dir = static_cast<security_direction>(direction); |
| 153 | + byte_buffer plaintext = make_byte_buffer(plaintext_cstr).value(); |
| 154 | + byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr).value(); |
| 155 | + |
| 156 | + // Create ciphering engine |
| 157 | + std::unique_ptr<ciphering_engine> nea = std::make_unique<ciphering_engine_nea2>(key, bearer, dir); |
| 158 | + |
| 159 | + // Apply ciphering and compare results |
| 160 | + security_result result = nea->apply_ciphering(plaintext.deep_copy().value(), 0, count); |
| 161 | + ASSERT_TRUE(result.buf.has_value()); |
| 162 | + EXPECT_EQ(result.buf.value(), ciphertext); |
| 163 | +} |
| 164 | + |
| 165 | +/// 128-NEA2 Test Set 4 |
| 166 | +/// Ref: TS 33.501 Sec. D.4.4, TS 33.401 Sec. C.1 128-EEA2 |
| 167 | +TEST_F(ciphering_engine_test, security_nea2_testset4) |
| 168 | +{ |
| 169 | + // Testdata in plain format |
| 170 | + const char* key_cstr = "aa1f95aea533bcb32eb63bf52d8f831a"; |
| 171 | + uint32_t count = 0x72d8c671; |
| 172 | + uint8_t bearer = 0x10; |
| 173 | + uint8_t direction = 1; |
| 174 | + // uint32_t length = 1022; |
| 175 | + const char* plaintext_cstr = "fb1b96c5c8badfb2e8e8edfde78e57f2ad81e74103fc430a534dcc37afcec70e1517bb06f27219dae49022d" |
| 176 | + "dc47a068de4c9496a951a6b09edbdc864c7adbd740ac50c022f3082bafd22d78197c5d508b977bca13f32e6" |
| 177 | + "52e74ba728576077ce628c535e87dc6077ba07d29068590c8cb5f1088e082cfa0ec961302d69cf3d44"; |
| 178 | + const char* ciphertext_cstr = "dfb440acb3773549efc04628aeb8d8156275230bdc690d94b00d8d95f28c4b56307f60f4ca55eba661ebba" |
| 179 | + "72ac808fa8c49e26788ed04a5d606cb418de74878b9a22f8ef29590bc4eb57c9faf7c41524a885b8979c42" |
| 180 | + "3f2f8f8e0592a9879201be7ff9777a162ab810feb324ba74c4c156e04d39097209653ac33e5a5f2d8864"; |
| 181 | + |
| 182 | + // Pack hex strings into srsran types |
| 183 | + sec_128_key key = make_sec_128_key(key_cstr); |
| 184 | + security_direction dir = static_cast<security_direction>(direction); |
| 185 | + byte_buffer plaintext = make_byte_buffer(plaintext_cstr).value(); |
| 186 | + byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr).value(); |
| 187 | + |
| 188 | + // Create ciphering engine |
| 189 | + std::unique_ptr<ciphering_engine> nea = std::make_unique<ciphering_engine_nea2>(key, bearer, dir); |
| 190 | + |
| 191 | + // Apply ciphering and compare results |
| 192 | + security_result result = nea->apply_ciphering(plaintext.deep_copy().value(), 0, count); |
| 193 | + ASSERT_TRUE(result.buf.has_value()); |
| 194 | + EXPECT_EQ(result.buf.value(), ciphertext); |
| 195 | +} |
| 196 | + |
| 197 | +/// 128-NEA2 Test Set 5 |
| 198 | +/// Ref: TS 33.501 Sec. D.4.4, TS 33.401 Sec. C.1 128-EEA2 |
| 199 | +TEST_F(ciphering_engine_test, security_nea2_testset5) |
| 200 | +{ |
| 201 | + // Testdata in plain format |
| 202 | + const char* key_cstr = "9618ae46891f86578eebe90ef7a1202e"; |
| 203 | + uint32_t count = 0xc675a64b; |
| 204 | + uint8_t bearer = 0x0c; |
| 205 | + uint8_t direction = 1; |
| 206 | + // uint32_t length = 1245; |
| 207 | + const char* plaintext_cstr = |
| 208 | + "8daa17b1ae050529c6827f28c0ef6a1242e93f8b314fb18a77f790ae049fedd612267fecaefc450174d76d9f9aa7755a30cd90a9a5874bf4" |
| 209 | + "8eaf70eea3a62a250a8b6bd8d9b08b08d64e32d1817777fb544d49cd49720e219dbf8bbed33904e1fd40a41d370a1f65745095687d47ba1d" |
| 210 | + "36d2349e23f644392c8ea9c49d40c13271aff264d0f24841d6465f0996ff84e65fc517c53efc3363c38492a8"; |
| 211 | + const char* ciphertext_cstr = |
| 212 | + "919c8c33d66789703d05a0d7ce82a2aeac4ee76c0f4da050335e8a84e7897ba5df2f36bd513e3d0c8578c7a0fcf043e03aa3a39fbaad7d15" |
| 213 | + "be074faa5d9029f71fb457b647834714b0e18f117fca10677945096c8c5f326ba8d6095eb29c3e36cf245d1622aafe921f7566c4f5d644f2" |
| 214 | + "f1fc0ec684ddb21349747622e209295d27ff3f95623371d49b147c0af486171f22cd04b1cbeb2658223e6938"; |
| 215 | + |
| 216 | + // Pack hex strings into srsran types |
| 217 | + sec_128_key key = make_sec_128_key(key_cstr); |
| 218 | + security_direction dir = static_cast<security_direction>(direction); |
| 219 | + byte_buffer plaintext = make_byte_buffer(plaintext_cstr).value(); |
| 220 | + byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr).value(); |
| 221 | + |
| 222 | + // Create ciphering engine |
| 223 | + std::unique_ptr<ciphering_engine> nea = std::make_unique<ciphering_engine_nea2>(key, bearer, dir); |
| 224 | + |
| 225 | + // Apply ciphering and compare results |
| 226 | + security_result result = nea->apply_ciphering(plaintext.deep_copy().value(), 0, count); |
| 227 | + ASSERT_TRUE(result.buf.has_value()); |
| 228 | + EXPECT_EQ(result.buf.value(), ciphertext); |
| 229 | +} |
| 230 | + |
| 231 | +/// 128-NEA2 Test Set 6 |
| 232 | +/// Ref: TS 33.501 Sec. D.4.4, TS 33.401 Sec. C.1 128-EEA2 |
| 233 | +TEST_F(ciphering_engine_test, security_nea2_testset6) |
| 234 | +{ |
| 235 | + // Testdata in plain format |
| 236 | + const char* key_cstr = "54f4e2e04c83786eec8fb5abe8e36566"; |
| 237 | + uint32_t count = 0xaca4f50f; |
| 238 | + uint8_t bearer = 0x0b; |
| 239 | + uint8_t direction = 0; |
| 240 | + // uint32_t length = 3861; |
| 241 | + const char* plaintext_cstr = |
| 242 | + "40981ba6824c1bfb4286b299783daf442c099f7ab0f58d5c8e46b104f08f01b41ab485472029b71d36bd1a3d90dc3a41b46d51672ac4c966" |
| 243 | + "3a2be063da4bc8d2808ce33e2cccbfc634e1b259060876a0fbb5a437ebcc8d31c19e4454318745e3fa16bb11adae248879fe52db2543e53c" |
| 244 | + "f445d3d828ce0bf5c560593d97278a59762dd0c2c9cd68d4496a792508614014b13b6aa51128c18cd6a90b87978c2ff1cabe7d9f898a411b" |
| 245 | + "fdb84f68f6727b1499cdd30df0443ab4a66653330bcba1105e4cec034c73e605b4310eaaadcfd5b0ca27ffd89d144df4792759427c9cc1f8" |
| 246 | + "cd8c87202364b8a687954cb05a8d4e2d99e73db160deb180ad0841e96741a5d59fe4189f15420026fe4cd12104932fb38f735340438aaf7e" |
| 247 | + "ca6fd5cfd3a195ce5abe65272af607ada1be65a6b4c9c0693234092c4d018f1756c6db9dc8a6d80b888138616b681262f954d0e771174878" |
| 248 | + "0d92291d86299972db741cfa4f37b8b56cdb18a7ca8218e86e4b4b716a4d04371fbec262fc5ad0b3819b187b97e55b1a4d7c19ee24c8b4d7" |
| 249 | + "723cfedf045b8acae4869517d80e50615d9035d5d9c5a40af602280b542597b0cb18619eeb35925759d195e100e8e4aa0c38a3c2abe0f3d8" |
| 250 | + "ff04f3c33c295069c23694b5bbeacdd542e28e8a94edb9119f412d054be1fa7200b090"; |
| 251 | + const char* ciphertext_cstr = |
| 252 | + "5cb72c6edc878f1566e10253afc364c9fa540d914db94cbee275d0917ca6af0d77acb4ef3bbe1a722b2ef5bd1d4b8e2aa5024ec1388a201e" |
| 253 | + "7bce7920aec615895f763a5564dcc4c482a2ee1d8bfecc4498eca83fbb75f9ab530e0dafbede2fa5895b82991b6277c529e0f2529d7f7960" |
| 254 | + "6be96706296dedfa9d7412b616958cb563c678c02825c30d0aee77c4c146d2765412421a808d13cec819694c75ad572e9b973d948b81a933" |
| 255 | + "7c3b2a17192e22c2069f7ed1162af44cdea817603665e807ce40c8e0dd9d6394dc6e31153fe1955c47afb51f2617ee0c5e3b8ef1ad7574ed" |
| 256 | + "343edc2743cc94c990e1f1fd264253c178dea739c0befeebcd9f9b76d49c1015c9fecf50e53b8b5204dbcd3eed863855dabcdcc94b31e318" |
| 257 | + "021568855c8b9e52a981957a112827f978ba960f1447911b317b5511fbcc7fb13ac153db74251117e4861eb9e83bffffc4eb7755579038e5" |
| 258 | + "7924b1f78b3e1ad90bab2a07871b72db5eef96c334044966db0c37cafd1a89e5646a3580eb6465f121dce9cb88d85b96cf23ccccd4280767" |
| 259 | + "bee8eeb23d8652461db6493103003baf89f5e18261ea43c84a92ebffffe4909dc46c5192f825f770600b9602c557b5f8b431a79d45977dd9" |
| 260 | + "c41b863da9e142e90020cfd074d6927b7ab3b6725d1a6f3f98b9c9daa8982aff067828"; |
| 261 | + |
| 262 | + // Pack hex strings into srsran types |
| 263 | + sec_128_key key = make_sec_128_key(key_cstr); |
| 264 | + security_direction dir = static_cast<security_direction>(direction); |
| 265 | + byte_buffer plaintext = make_byte_buffer(plaintext_cstr).value(); |
| 266 | + byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr).value(); |
| 267 | + |
| 268 | + // Create ciphering engine |
| 269 | + std::unique_ptr<ciphering_engine> nea = std::make_unique<ciphering_engine_nea2>(key, bearer, dir); |
| 270 | + |
| 271 | + // Apply ciphering and compare results |
| 272 | + security_result result = nea->apply_ciphering(plaintext.deep_copy().value(), 0, count); |
| 273 | + ASSERT_TRUE(result.buf.has_value()); |
| 274 | + EXPECT_EQ(result.buf.value(), ciphertext); |
| 275 | +} |
| 276 | + |
| 277 | +int main(int argc, char** argv) |
| 278 | +{ |
| 279 | + srslog::init(); |
| 280 | + ::testing::InitGoogleTest(&argc, argv); |
| 281 | + return RUN_ALL_TESTS(); |
| 282 | +} |
0 commit comments