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