| Index: net/tools/domain_security_preload_generator/cert_util.cc
 | 
| diff --git a/net/tools/domain_security_preload_generator/cert_util.cc b/net/tools/domain_security_preload_generator/cert_util.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..7935cbee5ce8674a7fe60915e4a11dd0927b9e9a
 | 
| --- /dev/null
 | 
| +++ b/net/tools/domain_security_preload_generator/cert_util.cc
 | 
| @@ -0,0 +1,105 @@
 | 
| +// 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/tools/domain_security_preload_generator/cert_util.h"
 | 
| +
 | 
| +#include <string>
 | 
| +
 | 
| +#include "base/base64.h"
 | 
| +#include "base/files/file_util.h"
 | 
| +#include "base/strings/string_util.h"
 | 
| +#include "base/strings/stringprintf.h"
 | 
| +#include "net/tools/domain_security_preload_generator/spki_hash.h"
 | 
| +#include "third_party/boringssl/src/include/openssl/crypto.h"
 | 
| +#include "third_party/boringssl/src/include/openssl/x509v3.h"
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +static const char* kPEMBeginBlock = "-----BEGIN %s-----";
 | 
| +static const char* kPEMEndBlock = "-----END %s-----";
 | 
| +
 | 
| +// Tries to extract the BASE64 encoded DER structure from |pem_input| by looking
 | 
| +// for the block type in |expected_block_type|. Only attempts the locate the
 | 
| +// first matching block. Other blocks are ignored. Returns true on success and
 | 
| +// copies the der structure to der_output. Returns false on error.
 | 
| +bool ParsePEM(base::StringPiece pem_input,
 | 
| +              base::StringPiece expected_block_type,
 | 
| +              std::string* der_output) {
 | 
| +  const std::string& block_start =
 | 
| +      base::StringPrintf(kPEMBeginBlock, expected_block_type.data());
 | 
| +  const std::string& block_end =
 | 
| +      base::StringPrintf(kPEMEndBlock, expected_block_type.data());
 | 
| +
 | 
| +  size_t block_start_pos = pem_input.find(block_start);
 | 
| +  if (block_start_pos == std::string::npos)
 | 
| +    return false;
 | 
| +  size_t base64_start_pos = block_start_pos + block_start.size();
 | 
| +
 | 
| +  size_t block_end_pos = pem_input.find(block_end, base64_start_pos);
 | 
| +  if (block_end_pos == std::string::npos)
 | 
| +    return false;
 | 
| +
 | 
| +  base::StringPiece base64_encoded =
 | 
| +      pem_input.substr(base64_start_pos, block_end_pos - base64_start_pos);
 | 
| +
 | 
| +  if (!base::Base64Decode(
 | 
| +          base::CollapseWhitespaceASCII(base64_encoded.as_string(), true),
 | 
| +          der_output)) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +bool CalculateSPKIHashFromCertificate(base::StringPiece pem_certificate,
 | 
| +                                      net::SPKIHash* out_hash) {
 | 
| +  std::string der;
 | 
| +  bool result = ParsePEM(pem_certificate, "CERTIFICATE", &der);
 | 
| +  if (!result) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  const unsigned char* der_data =
 | 
| +      reinterpret_cast<const unsigned char*>(der.c_str());
 | 
| +  X509* cert = d2i_X509(NULL, &der_data, base::checked_cast<long>(der.size()));
 | 
| +  if (!cert) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  bssl::UniquePtr<EVP_PKEY> key(X509_get_pubkey(cert));
 | 
| +  if (!key) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  uint8_t* spki_der;
 | 
| +  size_t spki_der_len;
 | 
| +  bssl::ScopedCBB cbb;
 | 
| +  if (!CBB_init(cbb.get(), 0) ||
 | 
| +      !EVP_marshal_public_key(cbb.get(), key.get()) ||
 | 
| +      !CBB_finish(cbb.get(), &spki_der, &spki_der_len)) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  out_hash->CalculateFromBytes(spki_der, spki_der_len);
 | 
| +  OPENSSL_free(spki_der);
 | 
| +  return result;
 | 
| +}
 | 
| +
 | 
| +bool CalculateSPKIHashFromKey(base::StringPiece pem_key,
 | 
| +                              net::SPKIHash* out_hash) {
 | 
| +  std::string der;
 | 
| +  bool result = ParsePEM(pem_key, "PUBLIC KEY", &der);
 | 
| +  if (!result) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  return out_hash->CalculateFromBytes(
 | 
| +      reinterpret_cast<const uint8_t*>(der.data()), der.size());
 | 
| +}
 | 
| +
 | 
| +void InitializeCryptoLibrary() {
 | 
| +  CRYPTO_library_init();
 | 
| +}
 | 
| 
 |