Skip to content

Commit 84d1e63

Browse files
sec: add unit tests for NEA2 ciphering engine
1 parent 7b2dc70 commit 84d1e63

File tree

2 files changed

+287
-0
lines changed

2 files changed

+287
-0
lines changed

tests/unittests/security/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@ set_directory_properties(PROPERTIES LABELS "security")
1111
add_executable(security_test security_test.cpp)
1212
target_link_libraries(security_test srsran_security srsran_support srslog gtest gtest_main)
1313
gtest_discover_tests(security_test)
14+
15+
add_executable(ciphering_engine_test ciphering_engine_test.cpp)
16+
target_include_directories(ciphering_engine_test PRIVATE ${CMAKE_SOURCE_DIR})
17+
target_link_libraries(ciphering_engine_test srsran_security srsran_support srslog gtest gtest_main)
18+
gtest_discover_tests(ciphering_engine_test)
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
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

Comments
 (0)