1 /* Copyright (c) 2016, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 
24 #include <my_global.h>
25 #include <gtest/gtest.h>
26 #include <gmock/gmock.h>
27 #include <sql_plugin_ref.h>
28 #include "keyring.cc"
29 #include "keyring_impl.cc"
30 #include "mock_logger.h"
31 
32 namespace keyring__api_unittest
33 {
34   using ::testing::StrEq;
35   using namespace keyring;
36 
37   class Keyring_api_test : public ::testing::Test
38   {
39   public:
Keyring_api_test()40     Keyring_api_test()
41     {}
~Keyring_api_test()42     ~Keyring_api_test()
43     {
44       delete[] plugin_name;
45       delete[] keyring_filename;
46     }
47   protected:
SetUp()48     virtual void SetUp()
49     {
50       plugin_name= new char[strlen("FakeKeyring")+1];
51       strcpy(plugin_name, "FakeKeyring");
52       keyring_filename= new char[strlen("./keyring")+1];
53       strcpy(keyring_filename, "./keyring");
54 
55       plugin_info.name.str= plugin_name;
56       plugin_info.name.length= strlen(plugin_name);
57       keyring_file_data_value= keyring_filename;
58 
59       remove(keyring_file_data_value);
60       remove("./keyring.backup");
61 
62       keyring_init_with_mock_logger();
63 
64       key_memory_KEYRING= PSI_NOT_INSTRUMENTED;
65       key_LOCK_keyring= PSI_NOT_INSTRUMENTED;
66       sample_key_data= "Robi";
67     }
TearDown()68     virtual void TearDown()
69     {
70       keyring_deinit_with_mock_logger();
71       remove(keyring_file_data_value);
72       remove("./keyring.backup");
73     }
74   protected:
75     void keyring_init_with_mock_logger();
76     void keyring_deinit_with_mock_logger();
77 
78     std::string sample_key_data;
79     char *plugin_name;
80     char *keyring_filename;
81     st_plugin_int plugin_info; //for Logger initialization
82   };
83 
keyring_init_with_mock_logger()84   void Keyring_api_test::keyring_init_with_mock_logger()
85   {
86     ASSERT_TRUE(keyring_init(&plugin_info) == 0);
87     //use MockLogger instead of Logger
88     logger.reset(new Mock_logger());
89   }
90 
keyring_deinit_with_mock_logger()91   void Keyring_api_test::keyring_deinit_with_mock_logger()
92   {
93     keyring_deinit(NULL);
94   }
95 
TEST_F(Keyring_api_test,StoreFetchRemove)96   TEST_F(Keyring_api_test, StoreFetchRemove)
97   {
98     EXPECT_EQ(mysql_key_store("Robert_key", "AES", "Robert", sample_key_data.c_str(),
99                               sample_key_data.length() + 1), 0);
100     char *key_type;
101     size_t key_len;
102     void *key;
103     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
104                               &key_len), 0);
105     EXPECT_STREQ("AES", key_type);
106     EXPECT_EQ(key_len, sample_key_data.length()+1);
107     ASSERT_TRUE(memcmp((char *)key, sample_key_data.c_str(), key_len) == 0);
108     my_free(key_type);
109     key_type= NULL;
110     my_free(key);
111     key= NULL;
112     EXPECT_EQ(mysql_key_remove("Robert_key", "Robert"), 0);
113     //make sure the key was removed - fetch it
114     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
115                               &key_len), 0);
116     ASSERT_TRUE(key == NULL);
117   }
118 
TEST_F(Keyring_api_test,CheckIfInmemoryKeyIsXORed)119   TEST_F(Keyring_api_test, CheckIfInmemoryKeyIsXORed)
120   {
121     EXPECT_EQ(mysql_key_store("Robert_key", "AES", "Robert", sample_key_data.c_str(),
122                               sample_key_data.length() + 1), 0);
123 
124     Key key_id("Robert_key", NULL, "Robert",NULL,0);
125     IKey* fetched_key= keys->fetch_key(&key_id);
126     ASSERT_TRUE(fetched_key != NULL);
127     std::string expected_key_signature= "Robert_keyRobert";
128     EXPECT_STREQ(fetched_key->get_key_signature()->c_str(), expected_key_signature.c_str());
129     EXPECT_EQ(fetched_key->get_key_signature()->length(), expected_key_signature.length());
130     uchar* key_data_fetched= fetched_key->get_key_data();
131     size_t key_data_fetched_size= fetched_key->get_key_data_size();
132     EXPECT_STREQ("AES", fetched_key->get_key_type()->c_str());
133 
134     //make sure that the key was xored before it was put into keys_container, i.e.
135     //the fetched key data is not equal to the key data that was stored
136     EXPECT_STRNE(sample_key_data.c_str(), reinterpret_cast<const char*>(key_data_fetched));
137     ASSERT_TRUE(sample_key_data.length()+1 == key_data_fetched_size);
138 
139     //now xor to get the data that was stored
140     fetched_key->xor_data();
141     EXPECT_STREQ(sample_key_data.c_str(), reinterpret_cast<const char*>(key_data_fetched));
142     ASSERT_TRUE(sample_key_data.length()+1 == key_data_fetched_size);
143     my_free(fetched_key->release_key_data());
144   }
145 
TEST_F(Keyring_api_test,FetchNotExisting)146   TEST_F(Keyring_api_test, FetchNotExisting)
147   {
148     char *key_type= NULL;
149     void *key= NULL;
150     size_t key_len= 0;
151     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
152                               &key_len), 0);
153     ASSERT_TRUE(key == NULL);
154   }
155 
TEST_F(Keyring_api_test,RemoveNotExisting)156   TEST_F(Keyring_api_test, RemoveNotExisting)
157   {
158     EXPECT_EQ(mysql_key_remove("Robert_key", "Robert"), 1);
159   }
160 
TEST_F(Keyring_api_test,StoreFetchNotExisting)161   TEST_F(Keyring_api_test, StoreFetchNotExisting)
162   {
163     EXPECT_EQ(mysql_key_store("Robert_key", "AES", "Robert", sample_key_data.c_str(),
164                               sample_key_data.length() + 1), 0);
165     char *key_type;
166     size_t key_len;
167     void *key;
168     EXPECT_EQ(mysql_key_fetch("NotExisting", &key_type, "Robert", &key, &key_len), 0);
169     ASSERT_TRUE(key == NULL);
170   }
171 
TEST_F(Keyring_api_test,StoreStoreStoreFetchRemove)172   TEST_F(Keyring_api_test, StoreStoreStoreFetchRemove)
173   {
174     std::string key_data1("Robi1");
175     std::string key_data2("Robi2");
176 
177     EXPECT_EQ(mysql_key_store("Robert_key", "AES", "Robert", sample_key_data.c_str(),
178                               sample_key_data.length() + 1), 0);
179     EXPECT_EQ(mysql_key_store("Robert_key1", "AES", "Robert", key_data1.c_str(),
180                               key_data1.length() + 1), 0);
181     EXPECT_EQ(mysql_key_store("Robert_key2", "AES", "Robert", key_data2.c_str(),
182                               key_data2.length() + 1), 0);
183     char *key_type;
184     size_t key_len;
185     void *key;
186     EXPECT_EQ(mysql_key_fetch("Robert_key1", &key_type, "Robert", &key,
187                               &key_len), 0);
188     EXPECT_STREQ("AES", key_type);
189     EXPECT_EQ(key_len, key_data1.length()+1);
190     ASSERT_TRUE(memcmp((char *)key, key_data1.c_str(), key_len) == 0);
191     my_free(key_type);
192     key_type= NULL;
193     my_free(key);
194     key= NULL;
195     EXPECT_EQ(mysql_key_remove("Robert_key2", "Robert"), 0);
196     //make sure the key was removed - fetch it
197     EXPECT_EQ(mysql_key_fetch("Robert_key2", &key_type, "Robert", &key,
198                               &key_len), 0);
199     ASSERT_TRUE(key == NULL);
200   }
201 
TEST_F(Keyring_api_test,StoreValidTypes)202   TEST_F(Keyring_api_test, StoreValidTypes)
203   {
204     EXPECT_EQ(mysql_key_store("Robert_key", "AES", "Robert", sample_key_data.c_str(),
205                               sample_key_data.length() + 1), 0);
206    EXPECT_EQ(mysql_key_store("Robert_key3", "RSA", "Robert", sample_key_data.c_str(),
207                               sample_key_data.length() + 1), 0);
208     EXPECT_EQ(mysql_key_store("Robert_key4", "DSA", "Robert", sample_key_data.c_str(),
209                               sample_key_data.length() + 1), 0);
210   }
211 
TEST_F(Keyring_api_test,StoreInvalidType)212   TEST_F(Keyring_api_test, StoreInvalidType)
213   {
214     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while storing key: invalid key_type")));
215     EXPECT_EQ(mysql_key_store("Robert_key", "YYY", "Robert", sample_key_data.c_str(),
216                               sample_key_data.length() + 1), 1);
217     char *key_type;
218     size_t key_len;
219     void *key;
220     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
221                               &key_len), 0);
222     ASSERT_TRUE(key == NULL);
223   }
224 
TEST_F(Keyring_api_test,StoreTwiceTheSameDifferentTypes)225   TEST_F(Keyring_api_test, StoreTwiceTheSameDifferentTypes)
226   {
227     EXPECT_EQ(mysql_key_store("Robert_key", "AES", "Robert", sample_key_data.c_str(),
228                               sample_key_data.length() + 1), 0);
229     EXPECT_EQ(mysql_key_store("Robert_key", "RSA", "Robert", sample_key_data.c_str(),
230                               sample_key_data.length() + 1), 1);
231   }
232 
TEST_F(Keyring_api_test,KeyGenerate)233   TEST_F(Keyring_api_test, KeyGenerate)
234   {
235     EXPECT_EQ(mysql_key_generate("Robert_key", "AES", "Robert", 128), 0);
236     char *key_type;
237     size_t key_len;
238     void *key;
239     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
240                               &key_len), 0);
241     EXPECT_STREQ("AES", key_type);
242     EXPECT_EQ(key_len, (size_t)128);
243     //Try accessing the last byte of key
244     char ch= ((char*)key)[key_len-1];
245     //Just to get rid of unused variable compiler error
246     (void)ch;
247     my_free(key);
248     my_free(key_type);
249   }
250 
TEST_F(Keyring_api_test,KeyringFileChange)251   TEST_F(Keyring_api_test, KeyringFileChange)
252   {
253     EXPECT_EQ(mysql_key_store("Robert_key", "AES", "Robert", sample_key_data.c_str(),
254                               sample_key_data.length() + 1), 0);
255     char *key_type;
256     size_t key_len;
257     void *key;
258     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
259                               &key_len), 0);
260     EXPECT_STREQ("AES", key_type);
261     EXPECT_EQ(key_len, sample_key_data.length()+1);
262     ASSERT_TRUE(memcmp((char *)key, sample_key_data.c_str(), key_len) == 0);
263     my_free(key_type);
264     key_type= NULL;
265     my_free(key);
266     key= NULL;
267     delete[] keyring_filename;
268     keyring_filename= new char[strlen("./new_keyring")+1];
269     strcpy(keyring_filename, "./new_keyring");
270     keyring_file_data_value= keyring_filename;
271     keyring_deinit_with_mock_logger();
272     keyring_init_with_mock_logger();
273     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
274                               &key_len), 0);
275     ASSERT_TRUE(key == NULL);
276     EXPECT_EQ(mysql_key_store("Robert_key_new", "AES", "Robert", sample_key_data.c_str(),
277                               sample_key_data.length() + 1), 0);
278     delete[] keyring_filename;
279     keyring_filename= new char[strlen("./keyring")+1];
280     strcpy(keyring_filename, "./keyring");
281     keyring_file_data_value= keyring_filename;
282     keyring_deinit_with_mock_logger();
283     keyring_init_with_mock_logger();
284     EXPECT_EQ(mysql_key_fetch("Robert_key_new", &key_type, "Robert", &key,
285                               &key_len), 0);
286     ASSERT_TRUE(key == NULL);
287     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
288                               &key_len), 0);
289     EXPECT_STREQ("AES", key_type);
290     EXPECT_EQ(key_len, sample_key_data.length()+1);
291     ASSERT_TRUE(memcmp((char *)key, sample_key_data.c_str(), key_len) == 0);
292     my_free(key_type);
293     key_type= NULL;
294     my_free(key);
295     key= NULL;
296     delete[] keyring_filename;
297     keyring_filename= new char[strlen("./new_keyring")+1];
298     strcpy(keyring_filename, "./new_keyring");
299     keyring_file_data_value= keyring_filename;
300     keyring_deinit_with_mock_logger();
301     keyring_init_with_mock_logger();
302     EXPECT_EQ(mysql_key_fetch("Robert_key_new", &key_type, "Robert", &key,
303                               &key_len), 0);
304     EXPECT_STREQ("AES", key_type);
305     EXPECT_EQ(key_len, sample_key_data.length()+1);
306     ASSERT_TRUE(memcmp((char *)key, sample_key_data.c_str(), key_len) == 0);
307     my_free(key_type);
308     key_type= NULL;
309     my_free(key);
310     key= NULL;
311     remove("./new_keyring");
312   }
313 
TEST_F(Keyring_api_test,NullUser)314   TEST_F(Keyring_api_test, NullUser)
315   {
316     EXPECT_EQ(mysql_key_store("Robert_key", "AES", NULL, sample_key_data.c_str(),
317                               sample_key_data.length() + 1), 0);
318     char *key_type;
319     size_t key_len;
320     void *key;
321     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, NULL, &key,
322                               &key_len), 0);
323     EXPECT_STREQ("AES", key_type);
324     EXPECT_EQ(key_len, sample_key_data.length()+1);
325     ASSERT_TRUE(memcmp((char *)key, sample_key_data.c_str(), key_len) == 0);
326     my_free(key_type);
327     key_type= NULL;
328     my_free(key);
329     key= NULL;
330     EXPECT_EQ(mysql_key_store("Robert_key", "RSA", NULL, sample_key_data.c_str(),
331                               sample_key_data.length() + 1), 1);
332     EXPECT_EQ(mysql_key_store("Kamil_key", "AES", NULL, sample_key_data.c_str(),
333                               sample_key_data.length() + 1), 0);
334     EXPECT_EQ(mysql_key_fetch("Kamil_key", &key_type, NULL, &key,
335                               &key_len), 0);
336     EXPECT_STREQ("AES", key_type);
337     EXPECT_EQ(key_len, sample_key_data.length()+1);
338     ASSERT_TRUE(memcmp((char *)key, sample_key_data.c_str(), key_len) == 0);
339     my_free(key_type);
340     key_type= NULL;
341     my_free(key);
342     key= NULL;
343     std::string arturs_key_data= "Artur";
344     EXPECT_EQ(mysql_key_store("Artur_key", "AES", "Artur", arturs_key_data.c_str(),
345                               arturs_key_data.length() + 1), 0);
346     EXPECT_EQ(mysql_key_fetch("Artur_key", &key_type, "Artur", &key,
347                               &key_len), 0);
348     EXPECT_STREQ("AES", key_type);
349     EXPECT_EQ(key_len, arturs_key_data.length()+1);
350     ASSERT_TRUE(memcmp((char *)key, arturs_key_data.c_str(), key_len) == 0);
351     my_free(key_type);
352     key_type= NULL;
353     my_free(key);
354     key= NULL;
355     EXPECT_EQ(mysql_key_remove("Robert_key", NULL) , 0);
356     EXPECT_EQ(mysql_key_fetch("Robert_key", &key_type, "Robert", &key,
357                               &key_len), 0);
358     ASSERT_TRUE(key == NULL);
359     EXPECT_EQ(mysql_key_fetch("Artur_key", &key_type, "Artur", &key,
360                               &key_len), 0);
361     EXPECT_STREQ("AES", key_type);
362     EXPECT_EQ(key_len, arturs_key_data.length()+1);
363     ASSERT_TRUE(memcmp((char *)key, arturs_key_data.c_str(), key_len) == 0);
364     my_free(key_type);
365     key_type= NULL;
366     my_free(key);
367     key= NULL;
368   }
369 
TEST_F(Keyring_api_test,NullKeyId)370   TEST_F(Keyring_api_test, NullKeyId)
371   {
372     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while storing key: key_id cannot be empty")));
373     EXPECT_EQ(mysql_key_store(NULL, "AES", "Robert", sample_key_data.c_str(),
374                               sample_key_data.length() + 1), 1);
375     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while storing key: key_id cannot be empty")));
376     EXPECT_EQ(mysql_key_store(NULL, "AES", NULL, sample_key_data.c_str(),
377                               sample_key_data.length() + 1), 1);
378     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while storing key: key_id cannot be empty")));
379     EXPECT_EQ(mysql_key_store("", "AES", "Robert", sample_key_data.c_str(),
380                               sample_key_data.length() + 1), 1);
381     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while storing key: key_id cannot be empty")));
382     EXPECT_EQ(mysql_key_store("", "AES", NULL, sample_key_data.c_str(),
383                               sample_key_data.length() + 1), 1);
384     char *key_type;
385     size_t key_len;
386     void *key;
387     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while fetching key: key_id cannot be empty")));
388     EXPECT_EQ(mysql_key_fetch(NULL, &key_type, "Robert", &key, &key_len), 1);
389     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while fetching key: key_id cannot be empty")));
390     EXPECT_EQ(mysql_key_fetch(NULL, &key_type, NULL, &key, &key_len), 1);
391     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while fetching key: key_id cannot be empty")));
392     EXPECT_EQ(mysql_key_fetch("", &key_type, "Robert", &key, &key_len), 1);
393     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while fetching key: key_id cannot be empty")));
394     EXPECT_EQ(mysql_key_fetch("", &key_type, NULL, &key, &key_len), 1);
395 
396     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while removing key: key_id cannot be empty")));
397     EXPECT_EQ(mysql_key_remove(NULL, "Robert") , 1);
398     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while removing key: key_id cannot be empty")));
399     EXPECT_EQ(mysql_key_remove(NULL, NULL) , 1);
400     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while removing key: key_id cannot be empty")));
401     EXPECT_EQ(mysql_key_remove("", "Robert") , 1);
402     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while removing key: key_id cannot be empty")));
403     EXPECT_EQ(mysql_key_remove("", NULL) , 1);
404 
405     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while generating key: key_id cannot be empty")));
406     EXPECT_EQ(mysql_key_generate(NULL, "AES", "Robert", 128), 1);
407     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while generating key: key_id cannot be empty")));
408     EXPECT_EQ(mysql_key_generate(NULL, "AES", NULL, 128), 1);
409     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while generating key: key_id cannot be empty")));
410     EXPECT_EQ(mysql_key_generate("", "AES", "Robert", 128), 1);
411     EXPECT_CALL(*((Mock_logger *)logger.get()), log(MY_ERROR_LEVEL, StrEq("Error while generating key: key_id cannot be empty")));
412     EXPECT_EQ(mysql_key_generate("", "AES", NULL, 128), 1);
413   }
414 
main(int argc,char ** argv)415   int main(int argc, char **argv) {
416     if (mysql_rwlock_init(key_LOCK_keyring, &LOCK_keyring))
417       return TRUE;
418     ::testing::InitGoogleTest(&argc, argv);
419     return RUN_ALL_TESTS();
420   }
421 }
422