Add unit tests related to Pkcs 12 02/237602/6
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 1 Jul 2020 20:53:14 +0000 (22:53 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 9 Jul 2020 16:38:08 +0000 (18:38 +0200)
* Implement unit tests.
* Add p12 test files for different types of keys.
* Slightly refactor PKCS12Serializable API.

Change-Id: I87e4d9ee50e75aff8cc4e042bb239983a1f3c4d9

src/manager/common/protocols.cpp
src/manager/common/protocols.h
src/manager/service/ckm-logic.cpp
unit-tests/CMakeLists.txt
unit-tests/resources/dsa.p12 [new file with mode: 0644]
unit-tests/resources/ecdsa.p12 [new file with mode: 0644]
unit-tests/resources/rsa.p12 [new file with mode: 0644]
unit-tests/test_pkcs12.cpp [new file with mode: 0644]

index d846ca4..a429daf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2016 - 2020 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.
@@ -120,8 +120,9 @@ PKCS12Serializable::PKCS12Serializable(IStream &stream)
        }
 }
 
-PKCS12Serializable::PKCS12Serializable(KeyShPtr &&privKey,
-                                                                          CertificateShPtr &&cert, CertificateShPtrVector &&chainCerts)
+PKCS12Serializable::PKCS12Serializable(KeyShPtr privKey,
+                                                                          CertificateShPtr cert,
+                                                                          CertificateShPtrVector chainCerts)
 {
        m_pkey = std::move(privKey);
        m_cert = std::move(cert);
index 8802578..9e03f18 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2014 - 2020 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.
@@ -117,9 +117,9 @@ struct COMMON_API PKCS12Serializable : public PKCS12Impl, ISerializable {
 
        explicit PKCS12Serializable(const PKCS12 &);
        explicit PKCS12Serializable(IStream &);
-       PKCS12Serializable(KeyShPtr &&privKey,
-                                          CertificateShPtr &&cert,
-                                          CertificateShPtrVector &&chainCerts);
+       PKCS12Serializable(KeyShPtr privKey,
+                                          CertificateShPtr cert,
+                                          CertificateShPtrVector chainCerts);
        void Serialize(IStream &) const;
 };
 
index 269b64f..867b527 100644 (file)
@@ -1086,8 +1086,7 @@ RawBuffer CKMLogic::getPKCS12(
 
                // prepare response
                if (retCode == CKM_API_SUCCESS)
-                       output = PKCS12Serializable(std::move(privKey), std::move(cert),
-                                                                               std::move(caChain));
+                       output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
        } catch (const Exc::Exception &e) {
                retCode = e.error();
        } catch (const CKM::Exception &e) {
index 2e4dc1a..35c05d8 100644 (file)
@@ -35,9 +35,11 @@ FIND_PACKAGE(Threads REQUIRED)
 
 SET(DB_TEST_DIR ${UNIT_TESTS_DIR}/db)
 SET(SS_TEST_DIR ${UNIT_TESTS_DIR}/secure-storage)
+SET(PKCS12_TEST_DIR ${UNIT_TESTS_DIR}/pkcs12/)
 
 ADD_DEFINITIONS("-DDB_TEST_DIR=\"${DB_TEST_DIR}\"")
 ADD_DEFINITIONS("-DSS_TEST_DIR=\"${SS_TEST_DIR}\"")
+ADD_DEFINITIONS("-DPKCS12_TEST_DIR=\"${PKCS12_TEST_DIR}\"")
 ADD_DEFINITIONS("-DBOOST_TEST_DYN_LINK")
 
 SET(MANAGER_PATH ${PROJECT_SOURCE_DIR}/src/manager)
@@ -85,6 +87,7 @@ SET(UNIT_TESTS_SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/test_key.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test_key-provider.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test_log-provider.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/test_pkcs12.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test_safe-buffer.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test_serialization.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test_sql.cpp
@@ -171,6 +174,13 @@ INSTALL(
 
 INSTALL(DIRECTORY resources/traverse DESTINATION ${DB_TEST_DIR})
 INSTALL(DIRECTORY secure-storage-old-data/ DESTINATION ${SS_TEST_DIR})
+INSTALL(
+       FILES
+               resources/rsa.p12
+               resources/dsa.p12
+               resources/ecdsa.p12
+       DESTINATION ${PKCS12_TEST_DIR}
+)
 
 CONFIGURE_FILE(
     ${PROJECT_SOURCE_DIR}/packaging/key-manager-unit-tests.manifest.in
diff --git a/unit-tests/resources/dsa.p12 b/unit-tests/resources/dsa.p12
new file mode 100644 (file)
index 0000000..3681c29
Binary files /dev/null and b/unit-tests/resources/dsa.p12 differ
diff --git a/unit-tests/resources/ecdsa.p12 b/unit-tests/resources/ecdsa.p12
new file mode 100644 (file)
index 0000000..3e3b9c0
Binary files /dev/null and b/unit-tests/resources/ecdsa.p12 differ
diff --git a/unit-tests/resources/rsa.p12 b/unit-tests/resources/rsa.p12
new file mode 100644 (file)
index 0000000..2e1fb9c
Binary files /dev/null and b/unit-tests/resources/rsa.p12 differ
diff --git a/unit-tests/test_pkcs12.cpp b/unit-tests/test_pkcs12.cpp
new file mode 100644 (file)
index 0000000..bb7b3fe
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (c) 2020 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
+ */
+
+#include <unordered_map>
+#include <fstream>
+#include <iterator>
+
+#include <boost_macros_wrapper.h>
+#include <test_common.h>
+
+#include <ckm/ckm-raw-buffer.h>
+#include <pkcs12-impl.h>
+#include <data-type.h>
+#include <protocols.h>
+#include <message-buffer.h>
+
+using namespace CKM;
+
+namespace {
+
+const RawBuffer& loadPkcs12(const std::string& path)
+{
+       static std::unordered_map<std::string, RawBuffer> pkcs12_map;
+
+       auto it = pkcs12_map.find(path);
+       if (it != pkcs12_map.end())
+               return it->second;
+
+       std::ifstream ifs(std::string(PKCS12_TEST_DIR) + path, std::ios::binary);
+       BOOST_REQUIRE(ifs);
+
+       ifs.unsetf(std::ios::skipws);
+       ifs.seekg(0, std::ios::end);
+       RawBuffer data;
+       data.reserve(ifs.tellg());
+       ifs.seekg(0, std::ios::beg);
+
+       data.insert(data.begin(),
+                   std::istream_iterator<decltype(data)::value_type>(ifs),
+                   std::istream_iterator<decltype(data)::value_type>());
+
+       return pkcs12_map.emplace(path, std::move(data)).first->second;
+}
+
+constexpr char PASSWORD[] = "secret";
+
+}
+
+BOOST_AUTO_TEST_SUITE(PKCS12_TEST)
+
+POSITIVE_TEST_CASE(create)
+{
+       const struct {
+               std::string path;
+               KeyType keyType;
+       } pkcsInfo[] = {
+               { "rsa.p12",   KeyType::KEY_RSA_PRIVATE },
+               { "dsa.p12",   KeyType::KEY_DSA_PRIVATE },
+               { "ecdsa.p12", KeyType::KEY_ECDSA_PRIVATE }
+       };
+
+       for (auto& info : pkcsInfo) {
+               PKCS12ShPtr pkcs;
+               BOOST_REQUIRE_NO_THROW(pkcs = PKCS12::create(loadPkcs12(info.path), PASSWORD));
+               BOOST_REQUIRE(pkcs);
+               BOOST_REQUIRE(!pkcs->empty());
+
+               KeyShPtr key;
+               BOOST_REQUIRE_NO_THROW(key = pkcs->getKey());
+               BOOST_REQUIRE(key && !key->empty());
+               BOOST_REQUIRE(key->getType() == info.keyType);
+
+               CertificateShPtr cert;
+               BOOST_REQUIRE_NO_THROW(cert = pkcs->getCertificate());
+               BOOST_REQUIRE(cert && !cert->empty());
+
+               CertificateShPtrVector cas;
+               BOOST_REQUIRE_NO_THROW(cas = pkcs->getCaCertificateShPtrVector());
+               BOOST_REQUIRE(!cas.empty());
+
+               PKCS12Impl pkcsImpl;
+               BOOST_REQUIRE_NO_THROW(pkcsImpl = PKCS12Impl(key, cert, cas));
+
+               BOOST_REQUIRE(!pkcsImpl.empty());
+       }
+}
+
+NEGATIVE_TEST_CASE(create)
+{
+       PKCS12ShPtr pkcs;
+
+       RawBuffer brokenPkcs = loadPkcs12("rsa.p12");
+       brokenPkcs.pop_back();
+       BOOST_REQUIRE_NO_THROW(pkcs = PKCS12::create(brokenPkcs, PASSWORD));
+       BOOST_REQUIRE(!pkcs);
+
+       BOOST_REQUIRE_NO_THROW(pkcs = PKCS12::create(loadPkcs12("rsa.p12"), "wrong pw"));
+       BOOST_REQUIRE(!pkcs);
+
+       BOOST_REQUIRE_NO_THROW(pkcs = PKCS12::create(loadPkcs12("rsa.p12"), ""));
+       BOOST_REQUIRE(!pkcs);
+
+       BOOST_REQUIRE_NO_THROW(pkcs = PKCS12::create(RawBuffer(), ""));
+       BOOST_REQUIRE(!pkcs);
+
+       BOOST_REQUIRE_NO_THROW(pkcs = PKCS12::create(RawBuffer(10), ""));
+       BOOST_REQUIRE(!pkcs);
+}
+
+NEGATIVE_TEST_CASE(empty)
+{
+       PKCS12Impl empty;
+       BOOST_REQUIRE(empty.empty());
+       BOOST_REQUIRE(!empty.getKey());
+       BOOST_REQUIRE(!empty.getCertificate());
+       BOOST_REQUIRE(empty.getCaCertificateShPtrVector().empty());
+}
+
+POSITIVE_TEST_CASE(pkcs12Serializable)
+{
+       RawBuffer der;
+
+       auto checkPkcs = [&](const PKCS12Serializable& ps) {
+               MessageBuffer msg;
+               msg.Push(MessageBuffer::Serialize(ps).Pop());
+               PKCS12Serializable deserialized(msg);
+               BOOST_REQUIRE(!deserialized.empty());
+
+               KeyShPtr deserializedKey;
+               BOOST_REQUIRE_NO_THROW(deserializedKey = deserialized.getKey());
+               BOOST_REQUIRE(deserializedKey && !deserializedKey->empty());
+               BOOST_REQUIRE(deserializedKey->getType() == KeyType::KEY_RSA_PRIVATE);
+               BOOST_REQUIRE(deserializedKey->getDER() == der);
+       };
+
+       PKCS12ShPtr pkcs;
+       BOOST_REQUIRE_NO_THROW(pkcs = PKCS12::create(loadPkcs12("rsa.p12"), PASSWORD));
+       BOOST_REQUIRE(pkcs);
+
+       KeyShPtr key;
+       BOOST_REQUIRE_NO_THROW(key = pkcs->getKey());
+       BOOST_REQUIRE(key && !key->empty());
+       BOOST_REQUIRE(key->getType() == KeyType::KEY_RSA_PRIVATE);
+       der = key->getDER();
+
+       PKCS12Serializable ps;
+       BOOST_REQUIRE_NO_THROW(ps = PKCS12Serializable(*pkcs));
+       checkPkcs(ps);
+
+       PKCS12Serializable ps2;
+       BOOST_REQUIRE_NO_THROW(ps2 = PKCS12Serializable(key,
+                                                       pkcs->getCertificate(),
+                                                       pkcs->getCaCertificateShPtrVector()));
+       checkPkcs(ps2);
+}
+
+NEGATIVE_TEST_CASE(pkcs12Serializable)
+{
+       auto checkEmptiness = [](const PKCS12Serializable& ps) {
+               MessageBuffer msg;
+               msg.Push(MessageBuffer::Serialize(ps).Pop());
+               PKCS12Serializable deserialized(msg);
+               BOOST_REQUIRE(deserialized.empty());
+       };
+
+       PKCS12Impl pkcs;
+
+       pkcs = PKCS12Impl(RawBuffer(), "");
+       PKCS12Serializable ps(pkcs);
+       checkEmptiness(ps);
+
+       pkcs = PKCS12Impl(RawBuffer(20), "");
+       PKCS12Serializable ps2(pkcs);
+       checkEmptiness(ps2);
+
+       pkcs = PKCS12Impl(loadPkcs12("rsa.p12"), "wrong pw");
+       PKCS12Serializable ps3(pkcs);
+       checkEmptiness(ps3);
+
+       PKCS12Serializable ps4;
+       checkEmptiness(ps4);
+}
+
+BOOST_AUTO_TEST_SUITE_END()