Add openssl to get certificate's subject-name-hash 96/113896/5
authorsangwan.kwon <sangwan.kwon@samsung.com>
Wed, 8 Feb 2017 09:13:40 +0000 (18:13 +0900)
committersangwan.kwon <sangwan.kwon@samsung.com>
Fri, 10 Feb 2017 05:11:17 +0000 (14:11 +0900)
* Custom certificate should be renamed as subject-name-hash.

Change-Id: I5dd52d7cd19cacd624e2d66b0e59183835011085
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
src/transec/AppCustomTrustAnchor.cpp
src/transec/CMakeLists.txt
src/transec/Certificate.cpp [new file with mode: 0644]
src/transec/Certificate.h [new file with mode: 0644]
tests/transec/CMakeLists.txt
tests/transec/test-certificate.cpp [new file with mode: 0644]
tests/transec/test-resource.h

index f2c43c4..4e32afe 100644 (file)
 #include <unistd.h>
 #include <cerrno>
 
+#include <set>
+
 #include <klay/filesystem.h>
 #include <klay/audit/logger.h>
 
+#include "Certificate.h"
 #include "Exception.h"
 
 namespace transec {
@@ -47,7 +50,7 @@ public:
 private:
        void linkTo(const std::string &src, const std::string &dst);
        void makeCustomBundle(void);
-       std::string getSubHashName(const std::string &filePath);
+       std::string getHashName(const std::string &filePath);
 
        std::string m_packageId;
        std::string m_appCertsPath;
@@ -56,6 +59,8 @@ private:
        std::string m_basePath;
        std::string m_sysCertsPath;
        std::string m_customCertsPath;
+
+       std::set<std::string> m_customCertNameSet;
 };
 
 AppCustomTrustAnchor::Impl::Impl(const std::string &packageId,
@@ -83,7 +88,6 @@ void AppCustomTrustAnchor::Impl::linkTo(const std::string &src,
 {
        errno = 0;
        int ret = ::symlink(src.c_str(), dst.c_str());
-       DEBUG("Make symlink from " << src << " to " << dst);
        if (ret != 0)
                throw std::logic_error("Fail to link " + src + " -> " + dst +
                                                           "[" + std::to_string(errno) + "]");
@@ -95,7 +99,6 @@ int AppCustomTrustAnchor::Impl::install(bool withSystemCerts) noexcept
 
        // make the package's custom directory
        runtime::File customDir(this->m_customCertsPath);
-       DEBUG(this->m_customCertsPath);
        if (customDir.exists()) {
                WARN("App custom certs directory is already exist. remove it!");
                customDir.remove(true);
@@ -108,6 +111,7 @@ int AppCustomTrustAnchor::Impl::install(bool withSystemCerts) noexcept
                while (iter != end) {
                        linkTo(iter->getPath(),
                                   this->m_customCertsPath + "/" + iter->getName());
+                       this->m_customCertNameSet.emplace(iter->getName());
                        ++iter;
                }
        }
@@ -120,15 +124,17 @@ int AppCustomTrustAnchor::Impl::install(bool withSystemCerts) noexcept
 
        runtime::DirectoryIterator iter(this->m_appCertsPath), end;
        while (iter != end) {
-               std::string hashName = this->getSubHashName(iter->getPath());
+               std::string hashName = this->getHashName(iter->getPath());
                linkTo(iter->getPath(),
                           this->m_customCertsPath + "/" + hashName);
+               this->m_customCertNameSet.emplace(std::move(hashName));
                ++iter;
        }
 
        this->makeCustomBundle();
 
-       INFO("Success to install : " << this->m_packageId);
+       INFO("Success to install[" << this->m_packageId <<
+                "] to " << this->m_customCertsPath);
        return 0;
 
        EXCEPTION_GUARD_END
@@ -158,28 +164,16 @@ int AppCustomTrustAnchor::Impl::launch(bool withSystemCerts)
                return -1;
 }
 
-/*
-       This function returns 'dummy file name' temporary.
-       It should be replaced with Openssl Class.
-*/
-std::string AppCustomTrustAnchor::Impl::getSubHashName(const std::string &filePath)
+std::string AppCustomTrustAnchor::Impl::getHashName(const std::string &filePath)
 {
-       runtime::File rawCert(filePath);
-
+       auto hashName = Certificate::getSubjectNameHash(filePath);
        int sameFileNameCnt = 0;
-       // TODO (openssl) rename certificates to subject_hash
-       runtime::DirectoryIterator iter(this->m_customCertsPath), end;
-       while(iter != end) {
-               if (iter->getName() == rawCert.getName())
-                       sameFileNameCnt++;
-
-               ++iter;
-       }
+       std::string uniqueName;
+       do {
+               uniqueName = hashName + "." + std::to_string(sameFileNameCnt++);
+       } while (this->m_customCertNameSet.find(uniqueName) != this->m_customCertNameSet.end());
 
-       size_t dotPos = rawCert.getName().rfind(".");
-       std::string fileName = rawCert.getName();
-       fileName.replace(dotPos + 1, std::string::npos, std::to_string(sameFileNameCnt));
-       return fileName;
+       return uniqueName;
 }
 
 void AppCustomTrustAnchor::Impl::makeCustomBundle(void)
index 47ca498..7446fe3 100644 (file)
 PKG_CHECK_MODULES(${TARGET_TRANSEC_LIB}_DEP
        REQUIRED
                klay
+               openssl
 )
 
 SET(${TARGET_TRANSEC_LIB}_SRCS
        InitLib.cpp
        Exception.cpp
+       Certificate.cpp
        AppCustomTrustAnchor.cpp
 )
 
diff --git a/src/transec/Certificate.cpp b/src/transec/Certificate.cpp
new file mode 100644 (file)
index 0000000..793575b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed 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.
+ */
+/*
+ * @file        Certificate.cpp
+ * @author      Sangwan Kwon (sangwan.kwon@samsung.com)
+ * @version     0.1
+ * @brief
+ */
+#include "Certificate.h"
+
+#include <cstdio>
+#include <vector>
+#include <memory>
+#include <stdexcept>
+
+#include <openssl/pem.h>
+
+namespace transec {
+
+namespace {
+
+using FilePtr = std::unique_ptr<FILE, decltype(&::fclose)>;
+using X509Ptr = std::unique_ptr<X509, decltype(&::X509_free)>;
+
+const int HASH_LENGTH = 8;
+
+} // namespace anonymous
+
+std::string Certificate::getSubjectNameHash(const std::string &path)
+{
+       FilePtr fp(fopen(path.c_str(), "r"), ::fclose);
+       if (fp == nullptr)
+               throw std::invalid_argument("Faild to open certificate.");
+
+       X509Ptr x509(::PEM_read_X509(fp.get(), NULL, NULL, NULL), ::X509_free);
+       if (x509 == nullptr) {
+               ::rewind(fp.get());
+               x509 = X509Ptr(::PEM_read_X509_AUX(fp.get(), NULL, NULL, NULL),
+                                          ::X509_free);
+       }
+
+       if (x509 == nullptr)
+               throw std::logic_error("Failed to read certificate.");
+
+       std::vector<char> buf(HASH_LENGTH + 1);
+       snprintf(buf.data(), buf.size(),
+                        "%08lx", ::X509_subject_name_hash(x509.get()));
+
+       return std::string(buf.data(), HASH_LENGTH);
+}
+
+} // namespace transec
diff --git a/src/transec/Certificate.h b/src/transec/Certificate.h
new file mode 100644 (file)
index 0000000..45d0172
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed 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.
+ */
+/*
+ * @file        Certificate.h
+ * @author      Sangwan Kwon (sangwan.kwon@samsung.com)
+ * @version     0.1
+ * @brief
+ */
+#pragma once
+
+#include <string>
+
+namespace transec {
+
+class Certificate {
+public:
+       static std::string getSubjectNameHash(const std::string &path);
+};
+
+} // namespace transec
index 90d2276..3d203c5 100644 (file)
@@ -19,6 +19,7 @@
 SET(TEST_SRCS
        main.cpp
        test-app-custom-trust-anchor.cpp
+       test-certificate.cpp
 )
 
 SET(TEST_TRANSEC_PATH "${CERT_SVC_TESTS}/transec")
diff --git a/tests/transec/test-certificate.cpp b/tests/transec/test-certificate.cpp
new file mode 100644 (file)
index 0000000..ac757b0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed 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.
+ */
+/*
+ * @file        test-certificate.cpp
+ * @author      Sangwan Kwon (sangwan.kwon@samsung.com)
+ * @version     0.1
+ * @brief       Unit test program of Certificate
+ */
+
+#include <dpl/test/test_runner.h>
+
+#include <iostream>
+
+#include <Certificate.h>
+
+#include "test-resource.h"
+
+RUNNER_TEST_GROUP_INIT(T0600_CERTIFICATE)
+
+using namespace transec;
+
+RUNNER_TEST(T0601_GET_SUBJECT_NAME_HASH)
+{
+       try {
+               auto hash = Certificate::getSubjectNameHash(TEST_PEM_PATH);
+               RUNNER_ASSERT_MSG(hash.compare(TEST_PEM_HASH) == 0,
+                                                 "Failed to get proper hash.");
+       } catch (const std::exception &e) {
+               std::cout << "std::exception occured." << e.what() << std::endl;
+       } catch (...) {
+               std::cout << "Unknown exception occured." << std::endl;
+       }
+}
index 94375eb..e40fba4 100644 (file)
@@ -26,3 +26,6 @@
 #define DUMMY_CERTS_DIR "/home/dummy"
 
 #define APP_CERTS_DIR TEST_TRANSEC_PATH "/certs"
+
+#define TEST_PEM_PATH APP_CERTS_DIR "/02265526.0"
+#define TEST_PEM_HASH "02265526"