• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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