// Copyright 2015 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_platform_key_util.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/string_piece.h" #include "base/threading/thread.h" #include "crypto/openssl_util.h" #include "net/cert/asn1_util.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/ec_key.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/rsa.h" namespace net { namespace { class SSLPlatformKeyTaskRunner { public: SSLPlatformKeyTaskRunner() : worker_thread_("Platform Key Thread") { base::Thread::Options options; options.joinable = false; worker_thread_.StartWithOptions(std::move(options)); } SSLPlatformKeyTaskRunner(const SSLPlatformKeyTaskRunner&) = delete; SSLPlatformKeyTaskRunner& operator=(const SSLPlatformKeyTaskRunner&) = delete; ~SSLPlatformKeyTaskRunner() = default; scoped_refptr task_runner() { return worker_thread_.task_runner(); } private: base::Thread worker_thread_; }; base::LazyInstance::Leaky g_platform_key_task_runner = LAZY_INSTANCE_INITIALIZER; } // namespace scoped_refptr GetSSLPlatformKeyTaskRunner() { return g_platform_key_task_runner.Get().task_runner(); } bssl::UniquePtr GetClientCertPublicKey( const X509Certificate* certificate) { crypto::OpenSSLErrStackTracer tracker(FROM_HERE); base::StringPiece spki; if (!asn1::ExtractSPKIFromDERCert( x509_util::CryptoBufferAsStringPiece(certificate->cert_buffer()), &spki)) { LOG(ERROR) << "Could not extract SPKI from certificate."; return nullptr; } CBS cbs; CBS_init(&cbs, reinterpret_cast(spki.data()), spki.size()); bssl::UniquePtr key(EVP_parse_public_key(&cbs)); if (!key || CBS_len(&cbs) != 0) { LOG(ERROR) << "Could not parse public key."; return nullptr; } return key; } bool GetClientCertInfo(const X509Certificate* certificate, int* out_type, size_t* out_max_length) { bssl::UniquePtr key = GetClientCertPublicKey(certificate); if (!key) { return false; } *out_type = EVP_PKEY_id(key.get()); *out_max_length = EVP_PKEY_size(key.get()); return true; } absl::optional> AddPSSPadding( EVP_PKEY* pubkey, const EVP_MD* md, base::span digest) { RSA* rsa = EVP_PKEY_get0_RSA(pubkey); if (!rsa) { return absl::nullopt; } std::vector ret(RSA_size(rsa)); if (digest.size() != EVP_MD_size(md) || !RSA_padding_add_PKCS1_PSS_mgf1(rsa, ret.data(), digest.data(), md, md, -1 /* salt length is digest length */)) { return absl::nullopt; } return ret; } } // namespace net