Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: extensions/common/cast/cast_cert_validator_nss.cc

Issue 792353002: Refactoring of Cast-related crypto code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/NetworkingPrivateCredentialsGetterCrOs/NetworkingPrivateCredentialsGetterChromeos/g Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 "extensions/common/cast/cast_cert_validator.h"
6
7 #include <cert.h>
8 #include <cryptohi.h>
9 #include <pk11pub.h>
10 #include <seccomon.h>
11
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "crypto/nss_util.h"
15 #include "crypto/scoped_nss_types.h"
16 #include "extensions/browser/api/cast_channel/cast_auth_ica.h"
17
18 namespace extensions {
19 namespace core_api {
20 namespace cast_crypto {
21
22 namespace {
23
24 typedef scoped_ptr<
25 CERTCertificate,
26 crypto::NSSDestroyer<CERTCertificate, CERT_DestroyCertificate>>
27 ScopedCERTCertificate;
28
29 class CertVerificationContextNSS : public CertVerificationContext {
30 public:
31 explicit CertVerificationContextNSS(CERTCertificate* x509) : x509_(x509) {}
Ryan Sleevi 2014/12/15 21:43:00 NAMING: s/x509/certificate/ (throughout)
sheretov 2014/12/16 08:44:21 Done.
32
33 VerificationResult VerifySignatureOverData(
34 const base::StringPiece& signature,
35 const base::StringPiece& data) const override {
36 // Verify that the |signature| matches |peer_cert|.
37 crypto::ScopedSECKEYPublicKey public_key(
38 CERT_ExtractPublicKey(x509_.get()));
39 if (!public_key.get()) {
40 return VerificationResult(
41 "Unable to extract public key from certificate",
42 VerificationResult::ERROR_CANNOT_EXTRACT_PUBLIC_KEY, PORT_GetError());
43 }
44 SECItem signature_item;
45 signature_item.type = siBuffer;
46 signature_item.data =
47 reinterpret_cast<unsigned char*>(const_cast<char*>(signature.data()));
48 signature_item.len = signature.length();
49 SECStatus verified = VFY_VerifyDataDirect(
50 reinterpret_cast<unsigned char*>(const_cast<char*>(data.data())),
51 data.size(), public_key.get(), &signature_item,
52 SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_SHA1, NULL, NULL);
53
54 if (verified != SECSuccess) {
55 return VerificationResult("Signature verification failed.",
56 VerificationResult::ERROR_SIGNATURE_INVALID,
57 PORT_GetError());
58 }
59 VLOG(1) << "Signature verification succeeded";
60 return VerificationResult();
61 }
62
63 std::string getCommonName() const override {
64 char* common_name = CERT_GetCommonName(&x509_->subject);
65 if (!common_name) {
66 LOG(ERROR) << "Certificate does not have common name.";
67 return "";
Ryan Sleevi 2014/12/15 21:43:00 s/""/std::string()
sheretov 2014/12/16 08:44:21 Done.
68 } else {
69 std::string result(common_name);
70 PORT_Free(common_name);
71 return result;
72 }
73 }
74
75 private:
76 ScopedCERTCertificate x509_;
77 };
78
79 } // namespace
80
81 VerificationResult VerifyCert(const base::StringPiece& device_cert,
82 const std::vector<std::string>& ica_certs,
83 CertVerificationContext** out_context) {
84 const std::string kErrorPrefix("Failed to verify credentials: ");
85
86 // If the list of intermediates is empty then use kPublicKeyICA1 as
87 // the trusted CA (legacy case).
88 // Otherwise, use the first intermediate in the list as long as it
89 // is in the allowed list of intermediates.
90 int num_intermediates = ica_certs.size();
91
92 VLOG(1) << "Response has " << num_intermediates << " intermediates";
Ryan Sleevi 2014/12/15 21:43:00 SPAM: This is spammy. Don't log like this. It does
sheretov 2014/12/16 08:44:21 Done.
93
94 base::StringPiece ica;
95 if (num_intermediates <= 0) {
96 ica = cast_channel::GetDefaultTrustedICAPublicKey();
97 } else {
98 ica = cast_channel::GetTrustedICAPublicKey(ica_certs[0]);
99 }
100 if (ica.empty()) {
101 return VerificationResult(
102 "Disallowed intermediate cert",
103 VerificationResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA);
104 }
105
106 SECItem trusted_ca_key_der;
107 trusted_ca_key_der.type = SECItemType::siDERCertBuffer;
108 trusted_ca_key_der.data =
109 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(ica.data()));
110 trusted_ca_key_der.len = ica.size();
111
112 crypto::EnsureNSSInit();
113 SECItem der_cert;
114 der_cert.type = siDERCertBuffer;
115 // Make a copy of certificate string so it is safe to type cast.
116 der_cert.data =
117 reinterpret_cast<unsigned char*>(const_cast<char*>(device_cert.data()));
118 der_cert.len = device_cert.length();
119
120 // Parse into a certificate structure.
121 ScopedCERTCertificate cert(CERT_NewTempCertificate(
122 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE));
123 if (!cert.get()) {
124 return VerificationResult("Failed to parse certificate.",
125 VerificationResult::ERROR_CERT_PARSING_FAILED,
126 PORT_GetError());
127 }
128
129 // Check that the certificate is signed by trusted CA.
130 // NOTE: We const_cast trusted_ca_key_der since on some platforms
131 // SECKEY_ImportDERPublicKey API takes in SECItem* and not const
132 // SECItem*.
133 crypto::ScopedSECKEYPublicKey ca_public_key(
134 SECKEY_ImportDERPublicKey(&trusted_ca_key_der, CKK_RSA));
135 if (!ca_public_key) {
136 return VerificationResult(
137 "Failed to import public key from CA certificate.",
138 VerificationResult::ERROR_CERT_PARSING_FAILED, PORT_GetError());
139 }
140 SECStatus verified = CERT_VerifySignedDataWithPublicKey(
141 &cert->signatureWrap, ca_public_key.get(), NULL);
142 if (verified != SECSuccess) {
143 return VerificationResult(
144 "Cert not signed by trusted CA",
145 VerificationResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA,
146 PORT_GetError());
147 }
148
149 VLOG(1) << "Cert signed by trusted CA";
Ryan Sleevi 2014/12/15 21:43:00 SPAM: This is also spammy. Considering you don't l
sheretov 2014/12/16 08:44:21 Done.
150
151 if (out_context)
152 *out_context = new CertVerificationContextNSS(cert.release());
153
154 return VerificationResult();
155 }
156
157 } // namespace cast_crypto
158 } // namespace core_api
159 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698