mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
125 lines
4.3 KiB
C++
125 lines
4.3 KiB
C++
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/ssl/ssl_private_key_test_util.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <vector>
|
|
|
|
#include "base/bind.h"
|
|
#include "base/containers/span.h"
|
|
#include "base/location.h"
|
|
#include "base/run_loop.h"
|
|
#include "crypto/openssl_util.h"
|
|
#include "net/base/net_errors.h"
|
|
#include "net/ssl/ssl_private_key.h"
|
|
#include "net/test/gtest_util.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "third_party/boringssl/src/include/openssl/bytestring.h"
|
|
#include "third_party/boringssl/src/include/openssl/digest.h"
|
|
#include "third_party/boringssl/src/include/openssl/evp.h"
|
|
#include "third_party/boringssl/src/include/openssl/rsa.h"
|
|
#include "third_party/boringssl/src/include/openssl/ssl.h"
|
|
|
|
using net::test::IsOk;
|
|
|
|
namespace net {
|
|
|
|
namespace {
|
|
|
|
bool VerifyWithOpenSSL(uint16_t algorithm,
|
|
base::span<const uint8_t> input,
|
|
EVP_PKEY* key,
|
|
base::span<const uint8_t> signature) {
|
|
bssl::ScopedEVP_MD_CTX ctx;
|
|
EVP_PKEY_CTX* pctx;
|
|
if (!EVP_DigestVerifyInit(ctx.get(), &pctx,
|
|
SSL_get_signature_algorithm_digest(algorithm),
|
|
nullptr, key)) {
|
|
return false;
|
|
}
|
|
if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
|
|
if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
|
|
!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* hash length */)) {
|
|
return false;
|
|
}
|
|
}
|
|
return EVP_DigestVerify(ctx.get(), signature.data(), signature.size(),
|
|
input.data(), input.size());
|
|
}
|
|
|
|
void OnSignComplete(base::RunLoop* loop,
|
|
Error* out_error,
|
|
std::vector<uint8_t>* out_signature,
|
|
Error error,
|
|
const std::vector<uint8_t>& signature) {
|
|
*out_error = error;
|
|
*out_signature = signature;
|
|
loop->Quit();
|
|
}
|
|
|
|
Error DoKeySigningWithWrapper(SSLPrivateKey* key,
|
|
uint16_t algorithm,
|
|
base::span<const uint8_t> input,
|
|
std::vector<uint8_t>* result) {
|
|
Error error;
|
|
base::RunLoop loop;
|
|
key->Sign(algorithm, input,
|
|
base::Bind(OnSignComplete, base::Unretained(&loop),
|
|
base::Unretained(&error), base::Unretained(result)));
|
|
loop.Run();
|
|
return error;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void TestSSLPrivateKeyMatches(SSLPrivateKey* key, const std::string& pkcs8) {
|
|
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
|
|
|
|
// Create the equivalent OpenSSL key.
|
|
CBS cbs;
|
|
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size());
|
|
bssl::UniquePtr<EVP_PKEY> openssl_key(EVP_parse_private_key(&cbs));
|
|
ASSERT_TRUE(openssl_key);
|
|
EXPECT_EQ(0u, CBS_len(&cbs));
|
|
|
|
// Test all supported algorithms.
|
|
std::vector<uint16_t> preferences = key->GetAlgorithmPreferences();
|
|
|
|
// To support TLS 1.1 and earlier, RSA keys must implicitly support MD5-SHA1,
|
|
// despite not being advertised.
|
|
preferences.push_back(SSL_SIGN_RSA_PKCS1_MD5_SHA1);
|
|
|
|
for (uint16_t algorithm : preferences) {
|
|
SCOPED_TRACE(
|
|
SSL_get_signature_algorithm_name(algorithm, 0 /* exclude curve */));
|
|
// BoringSSL will skip signatures algorithms that don't match the key type.
|
|
if (EVP_PKEY_id(openssl_key.get()) !=
|
|
SSL_get_signature_algorithm_key_type(algorithm)) {
|
|
continue;
|
|
}
|
|
// If the RSA key is too small for the hash, skip the algorithm. BoringSSL
|
|
// will filter this algorithm out and decline using it. In particular,
|
|
// 1024-bit RSA keys cannot sign RSA-PSS with SHA-512 and test keys are
|
|
// often 1024 bits.
|
|
if (SSL_is_signature_algorithm_rsa_pss(algorithm) &&
|
|
static_cast<size_t>(EVP_PKEY_size(openssl_key.get())) <
|
|
2 * EVP_MD_size(SSL_get_signature_algorithm_digest(algorithm)) +
|
|
2) {
|
|
continue;
|
|
}
|
|
|
|
// Test the key generates valid signatures.
|
|
std::vector<uint8_t> input(100, 'a');
|
|
std::vector<uint8_t> signature;
|
|
Error error = DoKeySigningWithWrapper(key, algorithm, input, &signature);
|
|
EXPECT_THAT(error, IsOk());
|
|
EXPECT_TRUE(
|
|
VerifyWithOpenSSL(algorithm, input, openssl_key.get(), signature));
|
|
}
|
|
}
|
|
|
|
} // namespace net
|