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

Unified 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: fixed typo from https://codereview.chromium.org/747223002 Created 5 years, 11 months 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 side-by-side diff with in-line comments
Download patch
Index: extensions/common/cast/cast_cert_validator_nss.cc
diff --git a/extensions/common/cast/cast_cert_validator_nss.cc b/extensions/common/cast/cast_cert_validator_nss.cc
new file mode 100644
index 0000000000000000000000000000000000000000..425da28f30649f649085d63a2ddd0c3d6bc31a14
--- /dev/null
+++ b/extensions/common/cast/cast_cert_validator_nss.cc
@@ -0,0 +1,155 @@
+// Copyright 2014 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 "extensions/common/cast/cast_cert_validator.h"
+
+#include <cert.h>
+#include <cryptohi.h>
+#include <pk11pub.h>
+#include <seccomon.h>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "extensions/browser/api/cast_channel/cast_auth_ica.h"
+
+namespace extensions {
+namespace core_api {
+namespace cast_crypto {
+
+namespace {
+
+typedef scoped_ptr<
+ CERTCertificate,
+ crypto::NSSDestroyer<CERTCertificate, CERT_DestroyCertificate>>
+ ScopedCERTCertificate;
+
+class CertVerificationContextNSS : public CertVerificationContext {
+ public:
+ explicit CertVerificationContextNSS(CERTCertificate* certificate)
+ : certificate_(certificate) {}
+
+ VerificationResult VerifySignatureOverData(
+ const base::StringPiece& signature,
+ const base::StringPiece& data) const override {
+ // Retrieve public key object
+ crypto::ScopedSECKEYPublicKey public_key_obj(
+ CERT_ExtractPublicKey(certificate_.get()));
+ if (!public_key_obj.get()) {
+ return VerificationResult(
+ "Failed to extract device certificate public key.",
+ VerificationResult::ERROR_CERT_INVALID);
+ }
+ // Verify signature.
+ SECItem signature_item;
+ signature_item.type = siBuffer;
+ signature_item.data =
+ reinterpret_cast<unsigned char*>(const_cast<char*>(signature.data()));
+ signature_item.len = signature.length();
+ if (VFY_VerifyDataDirect(
+ reinterpret_cast<unsigned char*>(const_cast<char*>(data.data())),
+ data.size(), public_key_obj.get(), &signature_item,
+ SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_SHA1, NULL,
+ NULL) != SECSuccess) {
+ return VerificationResult("Signature verification failed.",
+ VerificationResult::ERROR_SIGNATURE_INVALID,
+ PORT_GetError());
+ }
+ return VerificationResult();
+ }
+
+ std::string GetCommonName() const override {
+ char* common_name = CERT_GetCommonName(&certificate_->subject);
+ if (!common_name)
+ return std::string();
+
+ std::string result(common_name);
+ PORT_Free(common_name);
+ return result;
+ }
+
+ private:
+ ScopedCERTCertificate certificate_;
+};
+
+} // namespace
+
+VerificationResult VerifyDeviceCert(
+ const base::StringPiece& device_cert,
+ const std::vector<std::string>& ica_certs,
+ scoped_ptr<CertVerificationContext>* context) {
+ crypto::EnsureNSSInit();
+
+ // If the list of intermediates is empty then use kPublicKeyICA1 as
+ // the trusted CA (legacy case).
+ // Otherwise, use the first intermediate in the list as long as it
+ // is in the allowed list of intermediates.
+ base::StringPiece ica_public_key_der =
+ (ica_certs.size() == 0)
+ ? cast_channel::GetDefaultTrustedICAPublicKey()
+ : cast_channel::GetTrustedICAPublicKey(ica_certs[0]);
+
+ if (ica_public_key_der.empty()) {
+ return VerificationResult(
+ "Device certificate is not signed by a trusted CA",
+ VerificationResult::ERROR_CERT_UNTRUSTED);
+ }
+ // Initialize the ICA public key.
+ SECItem ica_public_key_der_item;
+ ica_public_key_der_item.type = SECItemType::siDERCertBuffer;
+ ica_public_key_der_item.data = const_cast<uint8_t*>(
+ reinterpret_cast<const uint8_t*>(ica_public_key_der.data()));
+ ica_public_key_der_item.len = ica_public_key_der.size();
+
+ crypto::ScopedSECKEYPublicKey ica_public_key_obj(
+ SECKEY_ImportDERPublicKey(&ica_public_key_der_item, CKK_RSA));
+ if (!ica_public_key_obj) {
+ return VerificationResult("Failed to import trusted public key.",
+ VerificationResult::ERROR_INTERNAL,
+ PORT_GetError());
+ }
+ SECItem device_cert_der_item;
+ device_cert_der_item.type = siDERCertBuffer;
+ // Make a copy of certificate string so it is safe to type cast.
+ device_cert_der_item.data =
+ reinterpret_cast<unsigned char*>(const_cast<char*>(device_cert.data()));
+ device_cert_der_item.len = device_cert.length();
+
+ // Parse into a certificate structure.
+ ScopedCERTCertificate device_cert_obj(CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &device_cert_der_item, NULL, PR_FALSE, PR_TRUE));
+ if (!device_cert_obj.get()) {
+ return VerificationResult("Failed to parse device certificate.",
+ VerificationResult::ERROR_CERT_INVALID,
+ PORT_GetError());
+ }
+ if (CERT_VerifySignedDataWithPublicKey(&device_cert_obj->signatureWrap,
+ ica_public_key_obj.get(),
+ NULL) != SECSuccess) {
+ return VerificationResult("Signature verification failed.",
+ VerificationResult::ERROR_SIGNATURE_INVALID,
+ PORT_GetError());
+ }
+ if (context) {
+ scoped_ptr<CertVerificationContext> tmp_context(
+ new CertVerificationContextNSS(device_cert_obj.release()));
+ tmp_context.swap(*context);
+ }
+
+ return VerificationResult();
+}
+
+std::string VerificationResult::GetLogString() const {
+ std::string nssError = "NSS Error Code: ";
+ nssError += base::IntToString(library_error_code);
+ return error_message.size()
+ ? std::string("Error: ") + error_message + ", " + nssError
+ : nssError;
+}
+
+} // namespace cast_crypto
+} // namespace core_api
+} // namespace extensions
« no previous file with comments | « extensions/common/cast/cast_cert_validator.cc ('k') | extensions/common/cast/cast_cert_validator_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698