From 7c1f3eac0deba1b3c9ec880b6adb6e15a40f2344 Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Wed, 8 Feb 2017 18:13:40 +0900 Subject: [PATCH] Add openssl to get certificate's subject-name-hash * Custom certificate should be renamed as subject-name-hash. Change-Id: I5dd52d7cd19cacd624e2d66b0e59183835011085 Signed-off-by: sangwan.kwon --- src/transec/AppCustomTrustAnchor.cpp | 42 ++++++++++------------- src/transec/CMakeLists.txt | 2 ++ src/transec/Certificate.cpp | 65 ++++++++++++++++++++++++++++++++++++ src/transec/Certificate.h | 33 ++++++++++++++++++ tests/transec/CMakeLists.txt | 1 + tests/transec/test-certificate.cpp | 46 +++++++++++++++++++++++++ tests/transec/test-resource.h | 3 ++ 7 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 src/transec/Certificate.cpp create mode 100644 src/transec/Certificate.h create mode 100644 tests/transec/test-certificate.cpp diff --git a/src/transec/AppCustomTrustAnchor.cpp b/src/transec/AppCustomTrustAnchor.cpp index f2c43c4..4e32afe 100644 --- a/src/transec/AppCustomTrustAnchor.cpp +++ b/src/transec/AppCustomTrustAnchor.cpp @@ -24,9 +24,12 @@ #include #include +#include + #include #include +#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 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) diff --git a/src/transec/CMakeLists.txt b/src/transec/CMakeLists.txt index 47ca498..7446fe3 100644 --- a/src/transec/CMakeLists.txt +++ b/src/transec/CMakeLists.txt @@ -19,11 +19,13 @@ 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 index 0000000..793575b --- /dev/null +++ b/src/transec/Certificate.cpp @@ -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 +#include +#include +#include + +#include + +namespace transec { + +namespace { + +using FilePtr = std::unique_ptr; +using X509Ptr = std::unique_ptr; + +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 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 index 0000000..45d0172 --- /dev/null +++ b/src/transec/Certificate.h @@ -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 + +namespace transec { + +class Certificate { +public: + static std::string getSubjectNameHash(const std::string &path); +}; + +} // namespace transec diff --git a/tests/transec/CMakeLists.txt b/tests/transec/CMakeLists.txt index 90d2276..3d203c5 100644 --- a/tests/transec/CMakeLists.txt +++ b/tests/transec/CMakeLists.txt @@ -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 index 0000000..ac757b0 --- /dev/null +++ b/tests/transec/test-certificate.cpp @@ -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 + +#include + +#include + +#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; + } +} diff --git a/tests/transec/test-resource.h b/tests/transec/test-resource.h index 94375eb..e40fba4 100644 --- a/tests/transec/test-resource.h +++ b/tests/transec/test-resource.h @@ -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" -- 2.7.4