1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chromeos/login/auth/challenge_response/cert_utils.h"
6 
7 #include <string>
8 
9 #include "base/logging.h"
10 #include "base/strings/string_piece.h"
11 #include "net/cert/asn1_util.h"
12 #include "net/cert/x509_certificate.h"
13 #include "net/cert/x509_util.h"
14 #include "third_party/boringssl/src/include/openssl/ssl.h"
15 
16 namespace chromeos {
17 
18 namespace {
19 
GetSubjectPublicKeyInfo(const net::X509Certificate & certificate,std::string * spki_der)20 bool GetSubjectPublicKeyInfo(const net::X509Certificate& certificate,
21                              std::string* spki_der) {
22   base::StringPiece spki_der_piece;
23   if (!net::asn1::ExtractSPKIFromDERCert(
24           net::x509_util::CryptoBufferAsStringPiece(certificate.cert_buffer()),
25           &spki_der_piece)) {
26     return false;
27   }
28   *spki_der = spki_der_piece.as_string();
29   return !spki_der->empty();
30 }
31 
32 }  // namespace
33 
34 base::Optional<ChallengeResponseKey::SignatureAlgorithm>
GetChallengeResponseKeyAlgorithmFromSsl(uint16_t ssl_algorithm)35 GetChallengeResponseKeyAlgorithmFromSsl(uint16_t ssl_algorithm) {
36   switch (ssl_algorithm) {
37     case SSL_SIGN_RSA_PKCS1_SHA1:
38       return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha1;
39     case SSL_SIGN_RSA_PKCS1_SHA256:
40       return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha256;
41     case SSL_SIGN_RSA_PKCS1_SHA384:
42       return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha384;
43     case SSL_SIGN_RSA_PKCS1_SHA512:
44       return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha512;
45     default:
46       // This algorithm is unsupported by ChallengeResponseKey.
47       return {};
48   }
49 }
50 
ExtractChallengeResponseKeyFromCert(const net::X509Certificate & certificate,const std::vector<ChallengeResponseKey::SignatureAlgorithm> & signature_algorithms,ChallengeResponseKey * challenge_response_key)51 bool ExtractChallengeResponseKeyFromCert(
52     const net::X509Certificate& certificate,
53     const std::vector<ChallengeResponseKey::SignatureAlgorithm>&
54         signature_algorithms,
55     ChallengeResponseKey* challenge_response_key) {
56   if (signature_algorithms.empty()) {
57     LOG(ERROR)
58         << "No signature algorithms provided for the challenge-response key";
59     return false;
60   }
61   std::string spki_der;
62   if (!GetSubjectPublicKeyInfo(certificate, &spki_der)) {
63     LOG(ERROR) << "Failed to extract Subject Public Key Information from the "
64                   "given certificate";
65     return false;
66   }
67   challenge_response_key->set_public_key_spki_der(spki_der);
68   challenge_response_key->set_signature_algorithms(signature_algorithms);
69   return true;
70 }
71 
72 }  // namespace chromeos
73