1 /* 2 * Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL 3 * project. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2015 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing (at) OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 */ 53 54 #include <openssl/evp.h> 55 56 #include <stdio.h> 57 #include <stdint.h> 58 #include <stdlib.h> 59 #include <string.h> 60 61 OPENSSL_MSVC_PRAGMA(warning(push)) 62 OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) 63 64 #include <map> 65 #include <string> 66 #include <utility> 67 #include <vector> 68 69 OPENSSL_MSVC_PRAGMA(warning(pop)) 70 71 #include <gtest/gtest.h> 72 73 #include <openssl/buf.h> 74 #include <openssl/bytestring.h> 75 #include <openssl/crypto.h> 76 #include <openssl/digest.h> 77 #include <openssl/err.h> 78 #include <openssl/rsa.h> 79 80 #include "../test/file_test.h" 81 #include "../test/test_util.h" 82 83 84 // evp_test dispatches between multiple test types. PrivateKey tests take a key 85 // name parameter and single block, decode it as a PEM private key, and save it 86 // under that key name. Decrypt, Sign, and Verify tests take a previously 87 // imported key name as parameter and test their respective operations. 88 89 static const EVP_MD *GetDigest(FileTest *t, const std::string &name) { 90 if (name == "MD5") { 91 return EVP_md5(); 92 } else if (name == "SHA1") { 93 return EVP_sha1(); 94 } else if (name == "SHA224") { 95 return EVP_sha224(); 96 } else if (name == "SHA256") { 97 return EVP_sha256(); 98 } else if (name == "SHA384") { 99 return EVP_sha384(); 100 } else if (name == "SHA512") { 101 return EVP_sha512(); 102 } 103 ADD_FAILURE() << "Unknown digest: " << name; 104 return nullptr; 105 } 106 107 static int GetKeyType(FileTest *t, const std::string &name) { 108 if (name == "RSA") { 109 return EVP_PKEY_RSA; 110 } 111 if (name == "EC") { 112 return EVP_PKEY_EC; 113 } 114 if (name == "DSA") { 115 return EVP_PKEY_DSA; 116 } 117 if (name == "Ed25519") { 118 return EVP_PKEY_ED25519; 119 } 120 ADD_FAILURE() << "Unknown key type: " << name; 121 return EVP_PKEY_NONE; 122 } 123 124 static int GetRSAPadding(FileTest *t, int *out, const std::string &name) { 125 if (name == "PKCS1") { 126 *out = RSA_PKCS1_PADDING; 127 return true; 128 } 129 if (name == "PSS") { 130 *out = RSA_PKCS1_PSS_PADDING; 131 return true; 132 } 133 if (name == "OAEP") { 134 *out = RSA_PKCS1_OAEP_PADDING; 135 return true; 136 } 137 ADD_FAILURE() << "Unknown RSA padding mode: " << name; 138 return false; 139 } 140 141 using KeyMap = std::map<std::string, bssl::UniquePtr<EVP_PKEY>>; 142 143 static bool ImportKey(FileTest *t, KeyMap *key_map, 144 EVP_PKEY *(*parse_func)(CBS *cbs), 145 int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) { 146 std::vector<uint8_t> input; 147 if (!t->GetBytes(&input, "Input")) { 148 return false; 149 } 150 151 CBS cbs; 152 CBS_init(&cbs, input.data(), input.size()); 153 bssl::UniquePtr<EVP_PKEY> pkey(parse_func(&cbs)); 154 if (!pkey) { 155 return false; 156 } 157 158 std::string key_type; 159 if (!t->GetAttribute(&key_type, "Type")) { 160 return false; 161 } 162 EXPECT_EQ(GetKeyType(t, key_type), EVP_PKEY_id(pkey.get())); 163 164 // The key must re-encode correctly. 165 bssl::ScopedCBB cbb; 166 uint8_t *der; 167 size_t der_len; 168 if (!CBB_init(cbb.get(), 0) || 169 !marshal_func(cbb.get(), pkey.get()) || 170 !CBB_finish(cbb.get(), &der, &der_len)) { 171 return false; 172 } 173 bssl::UniquePtr<uint8_t> free_der(der); 174 175 std::vector<uint8_t> output = input; 176 if (t->HasAttribute("Output") && 177 !t->GetBytes(&output, "Output")) { 178 return false; 179 } 180 EXPECT_EQ(Bytes(output), Bytes(der, der_len)) << "Re-encoding the key did not match."; 181 182 // Save the key for future tests. 183 const std::string &key_name = t->GetParameter(); 184 EXPECT_EQ(0u, key_map->count(key_name)) << "Duplicate key: " << key_name; 185 (*key_map)[key_name] = std::move(pkey); 186 return true; 187 } 188 189 // SetupContext configures |ctx| based on attributes in |t|, with the exception 190 // of the signing digest which must be configured externally. 191 static bool SetupContext(FileTest *t, EVP_PKEY_CTX *ctx) { 192 if (t->HasAttribute("RSAPadding")) { 193 int padding; 194 if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) || 195 !EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) { 196 return false; 197 } 198 } 199 if (t->HasAttribute("PSSSaltLength") && 200 !EVP_PKEY_CTX_set_rsa_pss_saltlen( 201 ctx, atoi(t->GetAttributeOrDie("PSSSaltLength").c_str()))) { 202 return false; 203 } 204 if (t->HasAttribute("MGF1Digest")) { 205 const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("MGF1Digest")); 206 if (digest == nullptr || !EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, digest)) { 207 return false; 208 } 209 } 210 if (t->HasAttribute("OAEPDigest")) { 211 const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("OAEPDigest")); 212 if (digest == nullptr || !EVP_PKEY_CTX_set_rsa_oaep_md(ctx, digest)) { 213 return false; 214 } 215 } 216 if (t->HasAttribute("OAEPLabel")) { 217 std::vector<uint8_t> label; 218 if (!t->GetBytes(&label, "OAEPLabel")) { 219 return false; 220 } 221 // For historical reasons, |EVP_PKEY_CTX_set0_rsa_oaep_label| expects to be 222 // take ownership of the input. 223 bssl::UniquePtr<uint8_t> buf( 224 reinterpret_cast<uint8_t *>(BUF_memdup(label.data(), label.size()))); 225 if (!buf || 226 !EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, buf.get(), label.size())) { 227 return false; 228 } 229 buf.release(); 230 } 231 return true; 232 } 233 234 static bool TestEVP(FileTest *t, KeyMap *key_map) { 235 if (t->GetType() == "PrivateKey") { 236 return ImportKey(t, key_map, EVP_parse_private_key, 237 EVP_marshal_private_key); 238 } 239 240 if (t->GetType() == "PublicKey") { 241 return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key); 242 } 243 244 int (*key_op_init)(EVP_PKEY_CTX *ctx) = nullptr; 245 int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, 246 const uint8_t *in, size_t in_len) = nullptr; 247 int (*md_op_init)(EVP_MD_CTX * ctx, EVP_PKEY_CTX * *pctx, const EVP_MD *type, 248 ENGINE *e, EVP_PKEY *pkey) = nullptr; 249 bool is_verify = false; 250 if (t->GetType() == "Decrypt") { 251 key_op_init = EVP_PKEY_decrypt_init; 252 key_op = EVP_PKEY_decrypt; 253 } else if (t->GetType() == "Sign") { 254 key_op_init = EVP_PKEY_sign_init; 255 key_op = EVP_PKEY_sign; 256 } else if (t->GetType() == "Verify") { 257 key_op_init = EVP_PKEY_verify_init; 258 is_verify = true; 259 } else if (t->GetType() == "SignMessage") { 260 md_op_init = EVP_DigestSignInit; 261 } else if (t->GetType() == "VerifyMessage") { 262 md_op_init = EVP_DigestVerifyInit; 263 is_verify = true; 264 } else if (t->GetType() == "Encrypt") { 265 key_op_init = EVP_PKEY_encrypt_init; 266 key_op = EVP_PKEY_encrypt; 267 } else { 268 ADD_FAILURE() << "Unknown test " << t->GetType(); 269 return false; 270 } 271 272 // Load the key. 273 const std::string &key_name = t->GetParameter(); 274 if (key_map->count(key_name) == 0) { 275 ADD_FAILURE() << "Could not find key " << key_name; 276 return false; 277 } 278 EVP_PKEY *key = (*key_map)[key_name].get(); 279 280 const EVP_MD *digest = nullptr; 281 if (t->HasAttribute("Digest")) { 282 digest = GetDigest(t, t->GetAttributeOrDie("Digest")); 283 if (digest == nullptr) { 284 return false; 285 } 286 } 287 288 // For verify tests, the "output" is the signature. Read it now so that, for 289 // tests which expect a failure in SetupContext, the attribute is still 290 // consumed. 291 std::vector<uint8_t> input, actual, output; 292 if (!t->GetBytes(&input, "Input") || 293 (is_verify && !t->GetBytes(&output, "Output"))) { 294 return false; 295 } 296 297 if (md_op_init) { 298 bssl::ScopedEVP_MD_CTX ctx; 299 EVP_PKEY_CTX *pctx; 300 if (!md_op_init(ctx.get(), &pctx, digest, nullptr, key) || 301 !SetupContext(t, pctx)) { 302 return false; 303 } 304 305 if (is_verify) { 306 return !!EVP_DigestVerify(ctx.get(), output.data(), output.size(), 307 input.data(), input.size()); 308 } 309 310 size_t len; 311 if (!EVP_DigestSign(ctx.get(), nullptr, &len, input.data(), input.size())) { 312 return false; 313 } 314 actual.resize(len); 315 if (!EVP_DigestSign(ctx.get(), actual.data(), &len, input.data(), 316 input.size()) || 317 !t->GetBytes(&output, "Output")) { 318 return false; 319 } 320 actual.resize(len); 321 EXPECT_EQ(Bytes(output), Bytes(actual)); 322 return true; 323 } 324 325 bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr)); 326 if (!ctx || 327 !key_op_init(ctx.get()) || 328 (digest != nullptr && 329 !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || 330 !SetupContext(t, ctx.get())) { 331 return false; 332 } 333 334 if (is_verify) { 335 return !!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), 336 input.data(), input.size()); 337 } 338 339 size_t len; 340 if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) { 341 return false; 342 } 343 actual.resize(len); 344 if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) { 345 return false; 346 } 347 348 // Encryption is non-deterministic, so we check by decrypting. 349 if (t->HasAttribute("CheckDecrypt")) { 350 size_t plaintext_len; 351 ctx.reset(EVP_PKEY_CTX_new(key, nullptr)); 352 if (!ctx || 353 !EVP_PKEY_decrypt_init(ctx.get()) || 354 (digest != nullptr && 355 !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || 356 !SetupContext(t, ctx.get()) || 357 !EVP_PKEY_decrypt(ctx.get(), nullptr, &plaintext_len, actual.data(), 358 actual.size())) { 359 return false; 360 } 361 output.resize(plaintext_len); 362 if (!EVP_PKEY_decrypt(ctx.get(), output.data(), &plaintext_len, 363 actual.data(), actual.size())) { 364 ADD_FAILURE() << "Could not decrypt result."; 365 return false; 366 } 367 output.resize(plaintext_len); 368 EXPECT_EQ(Bytes(input), Bytes(output)) << "Decrypted result mismatch."; 369 return true; 370 } 371 372 // Some signature schemes are non-deterministic, so we check by verifying. 373 if (t->HasAttribute("CheckVerify")) { 374 ctx.reset(EVP_PKEY_CTX_new(key, nullptr)); 375 if (!ctx || 376 !EVP_PKEY_verify_init(ctx.get()) || 377 (digest != nullptr && 378 !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || 379 !SetupContext(t, ctx.get())) { 380 return false; 381 } 382 if (t->HasAttribute("VerifyPSSSaltLength") && 383 !EVP_PKEY_CTX_set_rsa_pss_saltlen( 384 ctx.get(), 385 atoi(t->GetAttributeOrDie("VerifyPSSSaltLength").c_str()))) { 386 return false; 387 } 388 EXPECT_TRUE(EVP_PKEY_verify(ctx.get(), actual.data(), actual.size(), 389 input.data(), input.size())) 390 << "Could not verify result."; 391 return true; 392 } 393 394 // By default, check by comparing the result against Output. 395 if (!t->GetBytes(&output, "Output")) { 396 return false; 397 } 398 actual.resize(len); 399 EXPECT_EQ(Bytes(output), Bytes(actual)); 400 return true; 401 } 402 403 TEST(EVPTest, TestVectors) { 404 KeyMap key_map; 405 FileTestGTest("crypto/evp/evp_tests.txt", [&](FileTest *t) { 406 bool result = TestEVP(t, &key_map); 407 if (t->HasAttribute("Error")) { 408 ASSERT_FALSE(result) << "Operation unexpectedly succeeded."; 409 uint32_t err = ERR_peek_error(); 410 EXPECT_EQ(t->GetAttributeOrDie("Error"), ERR_reason_error_string(err)); 411 } else if (!result) { 412 ADD_FAILURE() << "Operation unexpectedly failed."; 413 } 414 }); 415 } 416