|
17 | 17 |
|
18 | 18 | const std::vector<unsigned> kStandardKeySizes = {1024, 2048, 3072, 4096}; |
19 | 19 |
|
| 20 | +struct CipherTestCase { |
| 21 | + const char* cipher_flag; // "-aes128", "-des3", etc. |
| 22 | + const char* cipher_name; // "AES-128-CBC", "DES3-CBC", etc. |
| 23 | +}; |
| 24 | + |
| 25 | +static const CipherTestCase kCipherTestCases[] = { |
| 26 | + {"-des3", "DES3-CBC"}, |
| 27 | + {"-aes128", "AES-128-CBC"}, |
| 28 | + {"-aes192", "AES-192-CBC"}, |
| 29 | + {"-aes256", "AES-256-CBC"}, |
| 30 | +}; |
| 31 | + |
20 | 32 |
|
21 | 33 | class GenRSATestBase : public ::testing::Test { |
22 | 34 | protected: |
@@ -63,7 +75,49 @@ class GenRSATestBase : public ::testing::Test { |
63 | 75 | unsigned actual_bits = RSA_bits(rsa.get()); |
64 | 76 | if (actual_bits != expected_bits) { |
65 | 77 | ADD_FAILURE() << "Key size mismatch. Expected: " << expected_bits |
66 | | - << " bits, Got: " << actual_bits << " bits"; |
| 78 | + << " bits, Got: " << actual_bits << " bits"; |
| 79 | + return false; |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + return true; |
| 84 | + } |
| 85 | + |
| 86 | + bool ValidateEncryptedKeyFile(const char *path, const char *password, unsigned expected_bits = 0) { |
| 87 | + if (!path) { |
| 88 | + ADD_FAILURE() << "Path parameter is null"; |
| 89 | + return false; |
| 90 | + } |
| 91 | + |
| 92 | + if (!password) { |
| 93 | + ADD_FAILURE() << "Password parameter is null"; |
| 94 | + return false; |
| 95 | + } |
| 96 | + |
| 97 | + bssl::UniquePtr<BIO> bio(BIO_new_file(path, "rb")); |
| 98 | + if (!bio) { |
| 99 | + ADD_FAILURE() << "Failed to open encrypted key file: " << path; |
| 100 | + return false; |
| 101 | + } |
| 102 | + |
| 103 | + bssl::UniquePtr<RSA> rsa( |
| 104 | + PEM_read_bio_RSAPrivateKey(bio.get(), nullptr, nullptr, |
| 105 | + const_cast<char*>(password))); |
| 106 | + if (!rsa) { |
| 107 | + ADD_FAILURE() << "Failed to parse encrypted RSA key from PEM file"; |
| 108 | + return false; |
| 109 | + } |
| 110 | + |
| 111 | + if (RSA_check_key(rsa.get()) != 1) { |
| 112 | + ADD_FAILURE() << "Encrypted RSA key failed consistency check"; |
| 113 | + return false; |
| 114 | + } |
| 115 | + |
| 116 | + if (expected_bits > 0) { |
| 117 | + unsigned actual_bits = RSA_bits(rsa.get()); |
| 118 | + if (actual_bits != expected_bits) { |
| 119 | + ADD_FAILURE() << "Key size mismatch. Expected: " << expected_bits |
| 120 | + << " bits, Got: " << actual_bits << " bits"; |
67 | 121 | return false; |
68 | 122 | } |
69 | 123 | } |
@@ -100,6 +154,10 @@ class GenRSAParamTest : public GenRSATestBase, |
100 | 154 | public ::testing::WithParamInterface<unsigned> {}; |
101 | 155 |
|
102 | 156 |
|
| 157 | +class GenRSACipherParamTest : public GenRSATestBase, |
| 158 | + public ::testing::WithParamInterface<CipherTestCase> {}; |
| 159 | + |
| 160 | + |
103 | 161 | TEST_P(GenRSAParamTest, GeneratesKeyFile) { |
104 | 162 | unsigned key_size = GetParam(); |
105 | 163 |
|
@@ -151,6 +209,36 @@ TEST_P(GenRSAParamTest, OpenSSLCompatibility) { |
151 | 209 | INSTANTIATE_TEST_SUITE_P(StandardKeySizes, GenRSAParamTest, |
152 | 210 | ::testing::ValuesIn(kStandardKeySizes)); |
153 | 211 |
|
| 212 | +TEST_P(GenRSACipherParamTest, EncryptedKeyGeneration) { |
| 213 | + const CipherTestCase& cipher_test = GetParam(); |
| 214 | + |
| 215 | + args_list_t args{cipher_test.cipher_flag, "-passout", "pass:testpassword", "-out", out_path_tool, "2048"}; |
| 216 | + EXPECT_TRUE(genrsaTool(args)) << cipher_test.cipher_name << " encrypted key generation should work"; |
| 217 | + EXPECT_TRUE(ValidateEncryptedKeyFile(out_path_tool, "testpassword")) |
| 218 | + << cipher_test.cipher_name << " encrypted key should be valid"; |
| 219 | +} |
| 220 | + |
| 221 | +TEST_P(GenRSACipherParamTest, OpenSSLCompatibility) { |
| 222 | + const CipherTestCase& cipher_test = GetParam(); |
| 223 | + |
| 224 | + if (!HasCrossCompatibilityTools()) { |
| 225 | + GTEST_SKIP() << "Skipping test: AWSLC_TOOL_PATH and/or OPENSSL_TOOL_PATH " |
| 226 | + "environment variables are not set"; |
| 227 | + return; |
| 228 | + } |
| 229 | + |
| 230 | + args_list_t args{cipher_test.cipher_flag, "-passout", "pass:testpassword", "-out", out_path_tool, "2048"}; |
| 231 | + EXPECT_TRUE(genrsaTool(args)) << "AWS-LC " << cipher_test.cipher_name << " key generation failed"; |
| 232 | + |
| 233 | + std::string verify_cmd = std::string(openssl_executable_path) + |
| 234 | + " rsa -in " + out_path_tool + |
| 235 | + " -passin pass:testpassword -check -noout"; |
| 236 | + EXPECT_EQ(system(verify_cmd.c_str()), 0) << "OpenSSL verification of AWS-LC " << cipher_test.cipher_name << " key failed"; |
| 237 | +} |
| 238 | + |
| 239 | +INSTANTIATE_TEST_SUITE_P(AllCiphers, GenRSACipherParamTest, |
| 240 | + ::testing::ValuesIn(kCipherTestCases)); |
| 241 | + |
154 | 242 | TEST_F(GenRSATest, DefaultKeyGeneration) { |
155 | 243 | args_list_t args{"-out", out_path_tool}; |
156 | 244 | EXPECT_TRUE(genrsaTool(args)) << "Default key generation failed"; |
@@ -210,17 +298,27 @@ TEST_F(GenRSATest, FileIOErrors) { |
210 | 298 | } |
211 | 299 |
|
212 | 300 | TEST_F(GenRSATest, ArgumentValidation) { |
213 | | - // Test missing key size (should use default) |
214 | | - { |
215 | | - args_list_t args{"-out", out_path_tool}; |
216 | | - EXPECT_TRUE(genrsaTool(args)) << "Default key size should work"; |
217 | | - EXPECT_TRUE(ValidateKeyFile(out_path_tool)) |
218 | | - << "Default key should be valid"; |
219 | | - } |
220 | | - |
221 | 301 | // Test help takes precedence |
222 | 302 | { |
223 | 303 | args_list_t args{"-help", "-out", out_path_tool, "2048"}; |
224 | 304 | EXPECT_TRUE(genrsaTool(args)) << "Help should work even with other args"; |
225 | 305 | } |
226 | 306 | } |
| 307 | + |
| 308 | +TEST_F(GenRSATest, CipherMutualExclusionValidation) { |
| 309 | + // Test that multiple cipher options are rejected |
| 310 | + { |
| 311 | + args_list_t args{"-aes128", "-aes256", "-passout", "pass:testpassword", "-out", out_path_tool, "2048"}; |
| 312 | + EXPECT_FALSE(genrsaTool(args)) << "Command should fail with multiple cipher options"; |
| 313 | + } |
| 314 | + |
| 315 | + { |
| 316 | + args_list_t args{"-aes128", "-des3", "-passout", "pass:testpassword", "-out", out_path_tool, "2048"}; |
| 317 | + EXPECT_FALSE(genrsaTool(args)) << "Command should fail with multiple cipher options"; |
| 318 | + } |
| 319 | + |
| 320 | + { |
| 321 | + args_list_t args{"-aes192", "-des3", "-passout", "pass:testpassword", "-out", out_path_tool, "2048"}; |
| 322 | + EXPECT_FALSE(genrsaTool(args)) << "Command should fail with multiple cipher options"; |
| 323 | + } |
| 324 | +} |
0 commit comments