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/dsa.h> 78 #include <openssl/err.h> 79 #include <openssl/rsa.h> 80 81 #include "../test/file_test.h" 82 #include "../test/test_util.h" 83 #include "../test/wycheproof_util.h" 84 85 86 // evp_test dispatches between multiple test types. PrivateKey tests take a key 87 // name parameter and single block, decode it as a PEM private key, and save it 88 // under that key name. Decrypt, Sign, and Verify tests take a previously 89 // imported key name as parameter and test their respective operations. 90 91 static const EVP_MD *GetDigest(FileTest *t, const std::string &name) { 92 if (name == "MD5") { 93 return EVP_md5(); 94 } else if (name == "SHA1") { 95 return EVP_sha1(); 96 } else if (name == "SHA224") { 97 return EVP_sha224(); 98 } else if (name == "SHA256") { 99 return EVP_sha256(); 100 } else if (name == "SHA384") { 101 return EVP_sha384(); 102 } else if (name == "SHA512") { 103 return EVP_sha512(); 104 } 105 ADD_FAILURE() << "Unknown digest: " << name; 106 return nullptr; 107 } 108 109 static int GetKeyType(FileTest *t, const std::string &name) { 110 if (name == "RSA") { 111 return EVP_PKEY_RSA; 112 } 113 if (name == "EC") { 114 return EVP_PKEY_EC; 115 } 116 if (name == "DSA") { 117 return EVP_PKEY_DSA; 118 } 119 if (name == "Ed25519") { 120 return EVP_PKEY_ED25519; 121 } 122 ADD_FAILURE() << "Unknown key type: " << name; 123 return EVP_PKEY_NONE; 124 } 125 126 static int GetRSAPadding(FileTest *t, int *out, const std::string &name) { 127 if (name == "PKCS1") { 128 *out = RSA_PKCS1_PADDING; 129 return true; 130 } 131 if (name == "PSS") { 132 *out = RSA_PKCS1_PSS_PADDING; 133 return true; 134 } 135 if (name == "OAEP") { 136 *out = RSA_PKCS1_OAEP_PADDING; 137 return true; 138 } 139 ADD_FAILURE() << "Unknown RSA padding mode: " << name; 140 return false; 141 } 142 143 using KeyMap = std::map<std::string, bssl::UniquePtr<EVP_PKEY>>; 144 145 static bool ImportKey(FileTest *t, KeyMap *key_map, 146 EVP_PKEY *(*parse_func)(CBS *cbs), 147 int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) { 148 std::vector<uint8_t> input; 149 if (!t->GetBytes(&input, "Input")) { 150 return false; 151 } 152 153 CBS cbs; 154 CBS_init(&cbs, input.data(), input.size()); 155 bssl::UniquePtr<EVP_PKEY> pkey(parse_func(&cbs)); 156 if (!pkey) { 157 return false; 158 } 159 160 std::string key_type; 161 if (!t->GetAttribute(&key_type, "Type")) { 162 return false; 163 } 164 EXPECT_EQ(GetKeyType(t, key_type), EVP_PKEY_id(pkey.get())); 165 166 // The key must re-encode correctly. 167 bssl::ScopedCBB cbb; 168 uint8_t *der; 169 size_t der_len; 170 if (!CBB_init(cbb.get(), 0) || 171 !marshal_func(cbb.get(), pkey.get()) || 172 !CBB_finish(cbb.get(), &der, &der_len)) { 173 return false; 174 } 175 bssl::UniquePtr<uint8_t> free_der(der); 176 177 std::vector<uint8_t> output = input; 178 if (t->HasAttribute("Output") && 179 !t->GetBytes(&output, "Output")) { 180 return false; 181 } 182 EXPECT_EQ(Bytes(output), Bytes(der, der_len)) << "Re-encoding the key did not match."; 183 184 // Save the key for future tests. 185 const std::string &key_name = t->GetParameter(); 186 EXPECT_EQ(0u, key_map->count(key_name)) << "Duplicate key: " << key_name; 187 (*key_map)[key_name] = std::move(pkey); 188 return true; 189 } 190 191 // SetupContext configures |ctx| based on attributes in |t|, with the exception 192 // of the signing digest which must be configured externally. 193 static bool SetupContext(FileTest *t, EVP_PKEY_CTX *ctx) { 194 if (t->HasAttribute("RSAPadding")) { 195 int padding; 196 if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) || 197 !EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) { 198 return false; 199 } 200 } 201 if (t->HasAttribute("PSSSaltLength") && 202 !EVP_PKEY_CTX_set_rsa_pss_saltlen( 203 ctx, atoi(t->GetAttributeOrDie("PSSSaltLength").c_str()))) { 204 return false; 205 } 206 if (t->HasAttribute("MGF1Digest")) { 207 const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("MGF1Digest")); 208 if (digest == nullptr || !EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, digest)) { 209 return false; 210 } 211 } 212 if (t->HasAttribute("OAEPDigest")) { 213 const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("OAEPDigest")); 214 if (digest == nullptr || !EVP_PKEY_CTX_set_rsa_oaep_md(ctx, digest)) { 215 return false; 216 } 217 } 218 if (t->HasAttribute("OAEPLabel")) { 219 std::vector<uint8_t> label; 220 if (!t->GetBytes(&label, "OAEPLabel")) { 221 return false; 222 } 223 // For historical reasons, |EVP_PKEY_CTX_set0_rsa_oaep_label| expects to be 224 // take ownership of the input. 225 bssl::UniquePtr<uint8_t> buf( 226 reinterpret_cast<uint8_t *>(BUF_memdup(label.data(), label.size()))); 227 if (!buf || 228 !EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, buf.get(), label.size())) { 229 return false; 230 } 231 buf.release(); 232 } 233 return true; 234 } 235 236 static bool TestEVP(FileTest *t, KeyMap *key_map) { 237 if (t->GetType() == "PrivateKey") { 238 return ImportKey(t, key_map, EVP_parse_private_key, 239 EVP_marshal_private_key); 240 } 241 242 if (t->GetType() == "PublicKey") { 243 return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key); 244 } 245 246 int (*key_op_init)(EVP_PKEY_CTX *ctx) = nullptr; 247 int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, 248 const uint8_t *in, size_t in_len) = nullptr; 249 int (*md_op_init)(EVP_MD_CTX * ctx, EVP_PKEY_CTX * *pctx, const EVP_MD *type, 250 ENGINE *e, EVP_PKEY *pkey) = nullptr; 251 bool is_verify = false; 252 if (t->GetType() == "Decrypt") { 253 key_op_init = EVP_PKEY_decrypt_init; 254 key_op = EVP_PKEY_decrypt; 255 } else if (t->GetType() == "Sign") { 256 key_op_init = EVP_PKEY_sign_init; 257 key_op = EVP_PKEY_sign; 258 } else if (t->GetType() == "Verify") { 259 key_op_init = EVP_PKEY_verify_init; 260 is_verify = true; 261 } else if (t->GetType() == "SignMessage") { 262 md_op_init = EVP_DigestSignInit; 263 } else if (t->GetType() == "VerifyMessage") { 264 md_op_init = EVP_DigestVerifyInit; 265 is_verify = true; 266 } else if (t->GetType() == "Encrypt") { 267 key_op_init = EVP_PKEY_encrypt_init; 268 key_op = EVP_PKEY_encrypt; 269 } else { 270 ADD_FAILURE() << "Unknown test " << t->GetType(); 271 return false; 272 } 273 274 // Load the key. 275 const std::string &key_name = t->GetParameter(); 276 if (key_map->count(key_name) == 0) { 277 ADD_FAILURE() << "Could not find key " << key_name; 278 return false; 279 } 280 EVP_PKEY *key = (*key_map)[key_name].get(); 281 282 const EVP_MD *digest = nullptr; 283 if (t->HasAttribute("Digest")) { 284 digest = GetDigest(t, t->GetAttributeOrDie("Digest")); 285 if (digest == nullptr) { 286 return false; 287 } 288 } 289 290 // For verify tests, the "output" is the signature. Read it now so that, for 291 // tests which expect a failure in SetupContext, the attribute is still 292 // consumed. 293 std::vector<uint8_t> input, actual, output; 294 if (!t->GetBytes(&input, "Input") || 295 (is_verify && !t->GetBytes(&output, "Output"))) { 296 return false; 297 } 298 299 if (md_op_init) { 300 bssl::ScopedEVP_MD_CTX ctx; 301 EVP_PKEY_CTX *pctx; 302 if (!md_op_init(ctx.get(), &pctx, digest, nullptr, key) || 303 !SetupContext(t, pctx)) { 304 return false; 305 } 306 307 if (is_verify) { 308 return !!EVP_DigestVerify(ctx.get(), output.data(), output.size(), 309 input.data(), input.size()); 310 } 311 312 size_t len; 313 if (!EVP_DigestSign(ctx.get(), nullptr, &len, input.data(), input.size())) { 314 return false; 315 } 316 actual.resize(len); 317 if (!EVP_DigestSign(ctx.get(), actual.data(), &len, input.data(), 318 input.size()) || 319 !t->GetBytes(&output, "Output")) { 320 return false; 321 } 322 actual.resize(len); 323 EXPECT_EQ(Bytes(output), Bytes(actual)); 324 return true; 325 } 326 327 bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr)); 328 if (!ctx || 329 !key_op_init(ctx.get()) || 330 (digest != nullptr && 331 !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || 332 !SetupContext(t, ctx.get())) { 333 return false; 334 } 335 336 if (is_verify) { 337 return !!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), 338 input.data(), input.size()); 339 } 340 341 size_t len; 342 if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) { 343 return false; 344 } 345 actual.resize(len); 346 if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) { 347 return false; 348 } 349 350 // Encryption is non-deterministic, so we check by decrypting. 351 if (t->HasAttribute("CheckDecrypt")) { 352 size_t plaintext_len; 353 ctx.reset(EVP_PKEY_CTX_new(key, nullptr)); 354 if (!ctx || 355 !EVP_PKEY_decrypt_init(ctx.get()) || 356 (digest != nullptr && 357 !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || 358 !SetupContext(t, ctx.get()) || 359 !EVP_PKEY_decrypt(ctx.get(), nullptr, &plaintext_len, actual.data(), 360 actual.size())) { 361 return false; 362 } 363 output.resize(plaintext_len); 364 if (!EVP_PKEY_decrypt(ctx.get(), output.data(), &plaintext_len, 365 actual.data(), actual.size())) { 366 ADD_FAILURE() << "Could not decrypt result."; 367 return false; 368 } 369 output.resize(plaintext_len); 370 EXPECT_EQ(Bytes(input), Bytes(output)) << "Decrypted result mismatch."; 371 return true; 372 } 373 374 // Some signature schemes are non-deterministic, so we check by verifying. 375 if (t->HasAttribute("CheckVerify")) { 376 ctx.reset(EVP_PKEY_CTX_new(key, nullptr)); 377 if (!ctx || 378 !EVP_PKEY_verify_init(ctx.get()) || 379 (digest != nullptr && 380 !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || 381 !SetupContext(t, ctx.get())) { 382 return false; 383 } 384 if (t->HasAttribute("VerifyPSSSaltLength") && 385 !EVP_PKEY_CTX_set_rsa_pss_saltlen( 386 ctx.get(), 387 atoi(t->GetAttributeOrDie("VerifyPSSSaltLength").c_str()))) { 388 return false; 389 } 390 EXPECT_TRUE(EVP_PKEY_verify(ctx.get(), actual.data(), actual.size(), 391 input.data(), input.size())) 392 << "Could not verify result."; 393 return true; 394 } 395 396 // By default, check by comparing the result against Output. 397 if (!t->GetBytes(&output, "Output")) { 398 return false; 399 } 400 actual.resize(len); 401 EXPECT_EQ(Bytes(output), Bytes(actual)); 402 return true; 403 } 404 405 TEST(EVPTest, TestVectors) { 406 KeyMap key_map; 407 FileTestGTest("crypto/evp/evp_tests.txt", [&](FileTest *t) { 408 bool result = TestEVP(t, &key_map); 409 if (t->HasAttribute("Error")) { 410 ASSERT_FALSE(result) << "Operation unexpectedly succeeded."; 411 uint32_t err = ERR_peek_error(); 412 EXPECT_EQ(t->GetAttributeOrDie("Error"), ERR_reason_error_string(err)); 413 } else if (!result) { 414 ADD_FAILURE() << "Operation unexpectedly failed."; 415 } 416 }); 417 } 418 419 static void RunWycheproofTest(const char *path) { 420 SCOPED_TRACE(path); 421 FileTestGTest(path, [](FileTest *t) { 422 t->IgnoreInstruction("key.type"); 423 // Extra ECDSA fields. 424 t->IgnoreInstruction("key.curve"); 425 t->IgnoreInstruction("key.keySize"); 426 t->IgnoreInstruction("key.wx"); 427 t->IgnoreInstruction("key.wy"); 428 t->IgnoreInstruction("key.uncompressed"); 429 // Extra RSA fields. 430 t->IgnoreInstruction("e"); 431 t->IgnoreInstruction("keyAsn"); 432 t->IgnoreInstruction("keysize"); 433 t->IgnoreInstruction("n"); 434 t->IgnoreAttribute("padding"); 435 t->IgnoreInstruction("keyJwk.alg"); 436 t->IgnoreInstruction("keyJwk.e"); 437 t->IgnoreInstruction("keyJwk.kid"); 438 t->IgnoreInstruction("keyJwk.kty"); 439 t->IgnoreInstruction("keyJwk.n"); 440 // Extra EdDSA fields. 441 t->IgnoreInstruction("key.pk"); 442 t->IgnoreInstruction("key.sk"); 443 t->IgnoreInstruction("jwk.crv"); 444 t->IgnoreInstruction("jwk.d"); 445 t->IgnoreInstruction("jwk.kid"); 446 t->IgnoreInstruction("jwk.kty"); 447 t->IgnoreInstruction("jwk.x"); 448 // Extra DSA fields. 449 t->IgnoreInstruction("key.g"); 450 t->IgnoreInstruction("key.p"); 451 t->IgnoreInstruction("key.q"); 452 t->IgnoreInstruction("key.y"); 453 454 std::vector<uint8_t> der; 455 ASSERT_TRUE(t->GetInstructionBytes(&der, "keyDer")); 456 CBS cbs; 457 CBS_init(&cbs, der.data(), der.size()); 458 bssl::UniquePtr<EVP_PKEY> key(EVP_parse_public_key(&cbs)); 459 ASSERT_TRUE(key); 460 461 const EVP_MD *md = nullptr; 462 if (t->HasInstruction("sha")) { 463 md = GetWycheproofDigest(t, "sha", true); 464 ASSERT_TRUE(md); 465 } 466 467 bool is_pss = t->HasInstruction("mgf"); 468 const EVP_MD *mgf1_md = nullptr; 469 int pss_salt_len = -1; 470 if (is_pss) { 471 ASSERT_EQ("MGF1", t->GetInstructionOrDie("mgf")); 472 mgf1_md = GetWycheproofDigest(t, "mgfSha", true); 473 474 std::string s_len; 475 ASSERT_TRUE(t->GetInstruction(&s_len, "sLen")); 476 pss_salt_len = atoi(s_len.c_str()); 477 } 478 479 std::vector<uint8_t> msg; 480 ASSERT_TRUE(t->GetBytes(&msg, "msg")); 481 std::vector<uint8_t> sig; 482 ASSERT_TRUE(t->GetBytes(&sig, "sig")); 483 WycheproofResult result; 484 ASSERT_TRUE(GetWycheproofResult(t, &result)); 485 486 if (EVP_PKEY_id(key.get()) == EVP_PKEY_DSA) { 487 // DSA is deprecated and is not usable via EVP. 488 DSA *dsa = EVP_PKEY_get0_DSA(key.get()); 489 uint8_t digest[EVP_MAX_MD_SIZE]; 490 unsigned digest_len; 491 ASSERT_TRUE( 492 EVP_Digest(msg.data(), msg.size(), digest, &digest_len, md, nullptr)); 493 int valid; 494 bool sig_ok = DSA_check_signature(&valid, digest, digest_len, sig.data(), 495 sig.size(), dsa) && 496 valid; 497 if (result == WycheproofResult::kValid) { 498 EXPECT_TRUE(sig_ok); 499 } else if (result == WycheproofResult::kInvalid) { 500 EXPECT_FALSE(sig_ok); 501 } else { 502 // this is a legacy signature, which may or may not be accepted. 503 } 504 } else { 505 bssl::ScopedEVP_MD_CTX ctx; 506 EVP_PKEY_CTX *pctx; 507 ASSERT_TRUE( 508 EVP_DigestVerifyInit(ctx.get(), &pctx, md, nullptr, key.get())); 509 if (is_pss) { 510 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)); 511 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1_md)); 512 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, pss_salt_len)); 513 } 514 int ret = EVP_DigestVerify(ctx.get(), sig.data(), sig.size(), msg.data(), 515 msg.size()); 516 if (result == WycheproofResult::kValid) { 517 EXPECT_EQ(1, ret); 518 } else if (result == WycheproofResult::kInvalid) { 519 EXPECT_EQ(0, ret); 520 } else { 521 // this is a legacy signature, which may or may not be accepted. 522 EXPECT_TRUE(ret == 1 || ret == 0); 523 } 524 } 525 }); 526 } 527 528 TEST(EVPTest, WycheproofDSA) { 529 RunWycheproofTest("third_party/wycheproof_testvectors/dsa_test.txt"); 530 } 531 532 TEST(EVPTest, WycheproofECDSAP224) { 533 RunWycheproofTest( 534 "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt"); 535 RunWycheproofTest( 536 "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt"); 537 RunWycheproofTest( 538 "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt"); 539 } 540 541 TEST(EVPTest, WycheproofECDSAP256) { 542 RunWycheproofTest( 543 "third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt"); 544 RunWycheproofTest( 545 "third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt"); 546 } 547 548 TEST(EVPTest, WycheproofECDSAP384) { 549 RunWycheproofTest( 550 "third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt"); 551 } 552 553 TEST(EVPTest, WycheproofECDSAP521) { 554 RunWycheproofTest( 555 "third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt"); 556 RunWycheproofTest( 557 "third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt"); 558 } 559 560 TEST(EVPTest, WycheproofEdDSA) { 561 RunWycheproofTest("third_party/wycheproof_testvectors/eddsa_test.txt"); 562 } 563 564 TEST(EVPTest, WycheproofRSAPKCS1) { 565 RunWycheproofTest( 566 "third_party/wycheproof_testvectors/rsa_signature_test.txt"); 567 } 568 569 TEST(EVPTest, WycheproofRSAPSS) { 570 RunWycheproofTest( 571 "third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt"); 572 RunWycheproofTest( 573 "third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt"); 574 RunWycheproofTest( 575 "third_party/wycheproof_testvectors/" 576 "rsa_pss_2048_sha256_mgf1_32_test.txt"); 577 RunWycheproofTest( 578 "third_party/wycheproof_testvectors/" 579 "rsa_pss_3072_sha256_mgf1_32_test.txt"); 580 RunWycheproofTest( 581 "third_party/wycheproof_testvectors/" 582 "rsa_pss_4096_sha256_mgf1_32_test.txt"); 583 RunWycheproofTest( 584 "third_party/wycheproof_testvectors/" 585 "rsa_pss_4096_sha512_mgf1_32_test.txt"); 586 RunWycheproofTest("third_party/wycheproof_testvectors/rsa_pss_misc_test.txt"); 587 } 588