Repository: kudu Updated Branches: refs/heads/master c4c770a45 -> 959a7835d
[security] method to check if X509 cert matches key Added a method to security::Cert interface to check whether X509 certificate matches the specified private key. Change-Id: I6732f8a1ad9ed1b1ab26b94b582af50e6b6d24b1 Reviewed-on: http://gerrit.cloudera.org:8080/5936 Reviewed-by: Dan Burkert <danburk...@apache.org> Tested-by: Kudu Jenkins Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/f369fcfa Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/f369fcfa Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/f369fcfa Branch: refs/heads/master Commit: f369fcfaf768d0561f5209115355328c72b04620 Parents: c4c770a Author: Alexey Serbin <aser...@cloudera.com> Authored: Tue Feb 7 21:09:26 2017 -0800 Committer: Alexey Serbin <aser...@cloudera.com> Committed: Wed Feb 8 20:10:10 2017 +0000 ---------------------------------------------------------------------- src/kudu/security/CMakeLists.txt | 1 + src/kudu/security/cert-test.cc | 81 +++++++++++++++++++++++++++++++++++ src/kudu/security/cert.cc | 7 +++ src/kudu/security/cert.h | 6 +++ 4 files changed, 95 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/f369fcfa/src/kudu/security/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/src/kudu/security/CMakeLists.txt b/src/kudu/security/CMakeLists.txt index afa78d2..8c217c0 100644 --- a/src/kudu/security/CMakeLists.txt +++ b/src/kudu/security/CMakeLists.txt @@ -108,6 +108,7 @@ if (NOT NO_TESTS) ${KUDU_MIN_TEST_LIBS}) ADD_KUDU_TEST(ca/cert_management-test) + ADD_KUDU_TEST(cert-test) ADD_KUDU_TEST(crypto-test) ADD_KUDU_TEST(test/mini_kdc-test) ADD_KUDU_TEST(tls_handshake-test) http://git-wip-us.apache.org/repos/asf/kudu/blob/f369fcfa/src/kudu/security/cert-test.cc ---------------------------------------------------------------------- diff --git a/src/kudu/security/cert-test.cc b/src/kudu/security/cert-test.cc new file mode 100644 index 0000000..ca36095 --- /dev/null +++ b/src/kudu/security/cert-test.cc @@ -0,0 +1,81 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include <utility> + +#include "kudu/security/cert.h" +#include "kudu/security/crypto.h" +#include "kudu/security/openssl_util.h" +#include "kudu/security/test/test_certs.h" +#include "kudu/util/status.h" +#include "kudu/util/test_macros.h" +#include "kudu/util/test_util.h" + +using std::pair; + +namespace kudu { +namespace security { + +// Test for various certificate-related functionality in the security library. +// These do not cover CA certificate mananagement part; check +// cert_management-test.cc for those. +class CertTest : public KuduTest { + public: + void SetUp() override { + ASSERT_OK(ca_cert_.FromString(kCaCert, DataFormat::PEM)); + ASSERT_OK(ca_private_key_.FromString(kCaPrivateKey, DataFormat::PEM)); + ASSERT_OK(ca_public_key_.FromString(kCaPublicKey, DataFormat::PEM)); + ASSERT_OK(ca_exp_cert_.FromString(kCaExpiredCert, DataFormat::PEM)); + ASSERT_OK(ca_exp_private_key_.FromString(kCaExpiredPrivateKey, + DataFormat::PEM)); + } + + protected: + Cert ca_cert_; + PrivateKey ca_private_key_; + PublicKey ca_public_key_; + + Cert ca_exp_cert_; + PrivateKey ca_exp_private_key_; +}; + +// Check X509 certificate/private key matching: match cases. +TEST_F(CertTest, CertMatchesRsaPrivateKey) { + const pair<const Cert*, const PrivateKey*> cases[] = { + { &ca_cert_, &ca_private_key_ }, + { &ca_exp_cert_, &ca_exp_private_key_ }, + }; + for (const auto& e : cases) { + EXPECT_OK(e.first->CheckKeyMatch(*e.second)); + } +} + +// Check X509 certificate/private key matching: mismatch cases. +TEST_F(CertTest, CertMismatchesRsaPrivateKey) { + const pair<const Cert*, const PrivateKey*> cases[] = { + { &ca_cert_, &ca_exp_private_key_ }, + { &ca_exp_cert_, &ca_private_key_ }, + }; + for (const auto& e : cases) { + const Status s = e.first->CheckKeyMatch(*e.second); + EXPECT_TRUE(s.IsRuntimeError()) << s.ToString(); + ASSERT_STR_CONTAINS(s.ToString(), "certificate does not match private key"); + } +} + +} // namespace security +} // namespace kudu http://git-wip-us.apache.org/repos/asf/kudu/blob/f369fcfa/src/kudu/security/cert.cc ---------------------------------------------------------------------- diff --git a/src/kudu/security/cert.cc b/src/kudu/security/cert.cc index 6b7d45c..a75d33a 100644 --- a/src/kudu/security/cert.cc +++ b/src/kudu/security/cert.cc @@ -23,6 +23,7 @@ #include <openssl/pem.h> #include <openssl/x509.h> +#include "kudu/security/crypto.h" #include "kudu/security/openssl_util.h" #include "kudu/security/openssl_util_bio.h" #include "kudu/util/status.h" @@ -62,6 +63,12 @@ string Cert::IssuerName() const { return X509NameToString(X509_get_issuer_name(data_.get())); } +Status Cert::CheckKeyMatch(const PrivateKey& key) const { + OPENSSL_RET_NOT_OK(X509_check_private_key(data_.get(), key.GetRawData()), + "certificate does not match private key"); + return Status::OK(); +} + Status Cert::GetServerEndPointChannelBindings(string* channel_bindings) const { // Find the signature type of the certificate. This corresponds to the digest // (hash) algorithm, and the public key type which signed the cert. http://git-wip-us.apache.org/repos/asf/kudu/blob/f369fcfa/src/kudu/security/cert.h ---------------------------------------------------------------------- diff --git a/src/kudu/security/cert.h b/src/kudu/security/cert.h index e43127f..fc2464b 100644 --- a/src/kudu/security/cert.h +++ b/src/kudu/security/cert.h @@ -27,6 +27,8 @@ class Status; namespace security { +class PrivateKey; + // Convert an X509_NAME object to a human-readable string. std::string X509NameToString(X509_NAME* name); @@ -39,6 +41,10 @@ class Cert : public RawDataWrapper<X509> { std::string SubjectName() const; std::string IssuerName() const; + // Check whether the specified private key matches the certificate. + // Return Status::OK() if key match the certificate. + Status CheckKeyMatch(const PrivateKey& key) const; + // Returns the 'tls-server-end-point' channel bindings for the certificate as // specified in RFC 5929. Status GetServerEndPointChannelBindings(std::string* channel_bindings) const;