1 #include <fstream>
2 #include <iostream>
3 #include <sstream>
4
5 #include "gtest/gtest.h"
6 #include "gflags/gflags.h"
7 #include "nugget/app/protoapi/control.pb.h"
8 #include "nugget/app/protoapi/header.pb.h"
9 #include "nugget/app/protoapi/testing_api.pb.h"
10 #include "src/macros.h"
11 #include "src/util.h"
12
13 using nugget::app::protoapi::AesGcmEncryptTest;
14 using nugget::app::protoapi::AesGcmEncryptTestResult;
15 using nugget::app::protoapi::APImessageID;
16 using nugget::app::protoapi::DcryptError;
17 using nugget::app::protoapi::Notice;
18 using nugget::app::protoapi::NoticeCode;
19 using nugget::app::protoapi::OneofTestParametersCase;
20 using nugget::app::protoapi::OneofTestResultsCase;
21 using std::cout;
22 using std::stringstream;
23 using std::unique_ptr;
24
25 using test_harness::TestHarness;
26
27 DEFINE_bool(nos_test_dump_protos, false, "Dump binary protobufs to a file.");
28 DEFINE_int32(test_input_number, -1, "Run a specific test input.");
29
30 #define ASSERT_MSG_TYPE(msg, type_) \
31 do{if(type_ != APImessageID::NOTICE && msg.type == APImessageID::NOTICE){ \
32 Notice received; \
33 received.ParseFromArray(reinterpret_cast<char *>(msg.data), msg.data_len); \
34 ASSERT_EQ(msg.type, type_) \
35 << msg.type << " is " << APImessageID_Name((APImessageID) msg.type) \
36 << "\n" << received.DebugString(); \
37 }else{ \
38 ASSERT_EQ(msg.type, type_) \
39 << msg.type << " is " << APImessageID_Name((APImessageID) msg.type); \
40 }}while(0)
41
42 #define ASSERT_SUBTYPE(msg, type_) \
43 EXPECT_GT(msg.data_len, 2); \
44 uint16_t subtype = (msg.data[0] << 8) | msg.data[1]; \
45 EXPECT_EQ(subtype, type_)
46
47 namespace {
48
49 using test_harness::BYTE_TIME;
50
51 class NuggetOsTest: public testing::Test {
52 protected:
53 static void SetUpTestCase();
54 static void TearDownTestCase();
55
56 public:
57 static unique_ptr<test_harness::TestHarness> harness;
58 };
59
60 unique_ptr<test_harness::TestHarness> NuggetOsTest::harness;
61
SetUpTestCase()62 void NuggetOsTest::SetUpTestCase() {
63 harness = TestHarness::MakeUnique();
64
65 if (!harness->UsingSpi()) {
66 EXPECT_TRUE(harness->SwitchFromConsoleToProtoApi());
67 EXPECT_TRUE(harness->ttyState());
68 }
69 }
70
TearDownTestCase()71 void NuggetOsTest::TearDownTestCase() {
72 harness->ReadUntil(test_harness::BYTE_TIME * 1024);
73 if (!harness->UsingSpi()) {
74 EXPECT_TRUE(harness->SwitchFromProtoApiToConsole(NULL));
75 }
76 harness = unique_ptr<test_harness::TestHarness>();
77 }
78
79 #include "src/test-data/NIST-CAVP/aes-gcm-cavp.h"
80
TEST_F(NuggetOsTest,AesGcm)81 TEST_F(NuggetOsTest, AesGcm) {
82 const int verbosity = harness->getVerbosity();
83 harness->setVerbosity(verbosity - 1);
84 harness->ReadUntil(test_harness::BYTE_TIME * 1024);
85
86 size_t i = 0;
87 size_t test_input_count = ARRAYSIZE(NIST_GCM_DATA);
88 if (FLAGS_test_input_number != -1) {
89 i = FLAGS_test_input_number;
90 test_input_count = FLAGS_test_input_number + 1;
91 }
92 for (; i < test_input_count; i++) {
93 const gcm_data *test_case = &NIST_GCM_DATA[i];
94
95 AesGcmEncryptTest request;
96 request.set_key(test_case->key, test_case->key_len / 8);
97 request.set_iv(test_case->IV, test_case->IV_len / 8);
98 request.set_plain_text(test_case->PT, test_case->PT_len / 8);
99 request.set_aad(test_case->AAD, test_case->AAD_len / 8);
100 request.set_tag_len(test_case->tag_len / 8);
101
102 if (FLAGS_nos_test_dump_protos) {
103 std::ofstream outfile;
104 outfile.open("AesGcmEncryptTest_" + std::to_string(test_case->key_len) +
105 ".proto.bin", std::ios_base::binary);
106 outfile << request.SerializeAsString();
107 outfile.close();
108 }
109
110 ASSERT_NO_ERROR(harness->SendOneofProto(
111 APImessageID::TESTING_API_CALL,
112 OneofTestParametersCase::kAesGcmEncryptTest,
113 request), "");
114
115 test_harness::raw_message msg;
116 ASSERT_NO_ERROR(harness->GetData(&msg, 4096 * BYTE_TIME), "");
117 ASSERT_MSG_TYPE(msg, APImessageID::TESTING_API_RESPONSE);
118 ASSERT_SUBTYPE(msg, OneofTestResultsCase::kAesGcmEncryptTestResult);
119
120 AesGcmEncryptTestResult result;
121 ASSERT_TRUE(result.ParseFromArray(reinterpret_cast<char *>(msg.data + 2),
122 msg.data_len - 2));
123 EXPECT_EQ(result.result_code(), DcryptError::DE_NO_ERROR)
124 << result.result_code() << " is "
125 << DcryptError_Name(result.result_code());
126
127 ASSERT_EQ(result.cipher_text().size(), test_case->PT_len / 8)
128 << "\n" << result.DebugString();
129 const uint8_t *CT = (const uint8_t *)test_case->CT;
130 stringstream ct_ss;
131 for (size_t j = 0; j < test_case->PT_len / 8; j++) {
132 if (CT[j] < 16) {
133 ct_ss << '0';
134 }
135 ct_ss << std::hex << (unsigned int)CT[j];
136 }
137 for (size_t j = 0; j < test_case->PT_len / 8; j++) {
138 ASSERT_EQ(result.cipher_text()[j] & 0x00FF, CT[j] & 0x00FF)
139 << "\n"
140 << "test_case: " << i << "\n"
141 << "result : " << result.DebugString()
142 << "CT : " << ct_ss.str() << "\n"
143 << "mis-match: " << j;
144 }
145
146 ASSERT_EQ(result.tag().size(), test_case->tag_len / 8)
147 << "\n" << result.DebugString();
148 const uint8_t *tag = (const uint8_t *)test_case->tag;
149 stringstream tag_ss;
150 for (size_t j = 0; j < test_case->tag_len / 8; j++) {
151 if (tag[j] < 16) {
152 tag_ss << '0';
153 }
154 tag_ss << std::hex << (unsigned int)tag[j];
155 }
156 for (size_t j = 0; j < test_case->tag_len / 8; j++) {
157 ASSERT_EQ(result.tag()[j] & 0x00ff, tag[j] & 0x00ff)
158 << "\n"
159 << "test_case: " << i << "\n"
160 << "result : " << result.DebugString()
161 << "TAG : " << tag_ss.str() << "\n"
162 << "mis-match: " << j;
163 }
164 }
165
166 harness->ReadUntil(test_harness::BYTE_TIME * 1024);
167 harness->setVerbosity(verbosity);
168 }
169
170 } // namespace
171