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;

Reply via email to