Improve KeyImpl & KeyAesImpl code coverage 73/235573/7
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 5 Jun 2020 19:50:34 +0000 (21:50 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Fri, 12 Jun 2020 12:07:09 +0000 (12:07 +0000)
Also unify key API.

KeyAesImpl() will now return an empty object instead of throwing. This will
unify the error code returned for symmetric and asymmetric keys from
ckmc_get_key(). It will also fix asynchronous C++ API. Observer will receive
an empty key instead of not being called at all.

Unify the type returned from empty keys. C++ API is a platform one and
getType() function is not used in tizen.org according to CodeGrok.

Change-Id: I7de8f32dfe59b1c5af441dfb9a0b8bee5c0d0bcf

src/manager/client/client-manager-impl.cpp
src/manager/common/key-aes-impl.cpp
src/manager/common/key-impl.cpp
src/manager/common/key-impl.h
unit-tests/test_key.cpp

index a1f70af..d5b2df5 100644 (file)
@@ -388,11 +388,11 @@ int Manager::Impl::getKey(const Alias &alias, const Password &password,
        KeyShPtr keyParsed;
 
        if (recvDataType.isSKey())
-               keyParsed = KeyShPtr(new KeyAESImpl(rawData));
+               keyParsed = Key::createAES(rawData);
        else
-               keyParsed = KeyShPtr(new KeyImpl(rawData));
+               keyParsed = Key::create(rawData);
 
-       if (keyParsed->empty()) {
+       if (!keyParsed) {
                LogDebug("Key empty - failed to parse!");
                return CKM_API_ERROR_BAD_RESPONSE;
        }
index 54c8d61..a57e3fc 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+/* Copyright (c) 2015 - 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.
@@ -34,7 +34,7 @@ KeyAESImpl::KeyAESImpl(const RawBuffer &buf) : m_key(buf)
                break;
 
        default:
-               throw std::invalid_argument("invalid AES key size");
+               m_key.clear();
        }
 }
 
@@ -45,7 +45,7 @@ bool KeyAESImpl::empty() const
 
 KeyType KeyAESImpl::getType() const
 {
-       return KeyType::KEY_AES;
+       return empty() ? KeyType::KEY_NONE : KeyType::KEY_AES;
 }
 
 RawBuffer KeyAESImpl::getDER() const
@@ -67,10 +67,6 @@ KeyShPtr Key::createAES(const RawBuffer &raw)
                        output.reset();
 
                return output;
-       } catch (const std::bad_alloc &) {
-               LogDebug("Bad alloc during KeyAESImpl creation");
-       } catch (const std::invalid_argument &e) {
-               LogDebug(e.what());
        } catch (...) {
                LogError("Critical error: Unknown exception was caught during KeyAESImpl creation");
        }
index 63c4be5..bc917ec 100644 (file)
@@ -1,4 +1,4 @@
-/* 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.
@@ -81,10 +81,6 @@ CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY *pkey)
 
 } // anonymous namespace
 
-KeyImpl::KeyImpl() : m_pkey(nullptr, EVP_PKEY_free), m_type(KeyType::KEY_NONE)
-{
-}
-
 KeyImpl::KeyImpl(const RawBuffer &buf, const Password &password) :
        m_pkey(nullptr, EVP_PKEY_free),
        m_type(KeyType::KEY_NONE)
@@ -192,8 +188,10 @@ KeyImpl::KeyImpl(EvpShPtr pkey, KeyType type) : m_pkey(pkey), m_type(type)
                break;
        }
 
-       // verify if actual key type matches the expected tpe
-       int given_key_type = EVP_PKEY_type(EVP_PKEY_id(pkey.get()));
+       // verify if actual key type matches the expected type
+       int given_key_type = EVP_PKEY_NONE;
+       if (pkey)
+               given_key_type = EVP_PKEY_type(EVP_PKEY_id(pkey.get()));
 
        if (given_key_type == EVP_PKEY_NONE || expected_type != given_key_type) {
                m_pkey.reset();
@@ -255,8 +253,6 @@ KeyShPtr Key::create(const RawBuffer &raw, const Password &password)
                        output.reset();
 
                return output;
-       } catch (const std::bad_alloc &) {
-               LogDebug("Bad alloc was catch during KeyImpl creation");
        } catch (...) {
                LogError("Critical error: Unknown exception was caught during KeyImpl creation");
        }
index b31c904..dbd92d7 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000 - 2013 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.
@@ -33,7 +33,6 @@ class COMMON_API KeyImpl : public Key {
 public:
        using EvpShPtr = std::shared_ptr<EVP_PKEY>;
 
-       KeyImpl();
        KeyImpl(const KeyImpl &second) = delete;
        KeyImpl &operator=(const KeyImpl &second) = delete;
        KeyImpl(const RawBuffer &buffer, const Password &password = Password());
@@ -44,12 +43,6 @@ public:
        virtual RawBuffer getDERPUB() const;
        virtual RawBuffer getDERPRV() const;
        virtual EvpShPtr getEvpShPtr() const;
-       /* //TODO
-       virtual ElipticCurve getCurve() const
-       {
-           return ElipticCurve::prime192v1;
-       }
-       */
 
        virtual int getSize() const
        {
index 20c3d7b..7df894b 100644 (file)
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
+
+#include <string>
+
+#include <boost_macros_wrapper.h>
+#include <test_common.h>
+
 #include <key-impl.h>
 #include <key-aes-impl.h>
+#include <data-type.h>
 
-#include <boost_macros_wrapper.h>
-#include <string>
+using namespace CKM;
 
 namespace {
-const std::string PUBKEY_PEM =
-       "-----BEGIN PUBLIC KEY-----\n"
-       "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0EJRdUtd2th0vTVF7Qxv\n"
-       "DKzyFCF3w9vC9IDE/Yr12w+a9jd0s7/eG96qTHIYffS3B7x2MB+d4n+SR3W0qmYh\n"
-       "7xk8qfEgH3daeDoV59IZ9r543KM+g8jm6KffYGX1bIJVVY5OhBRbO9nY6byYpd5k\n"
-       "bCIUB6dCf7/WrQl1aIdLGFIegAzPGFPXDcU6F192686x54bxt/itMX4agHJ9ZC/r\n"
-       "rTBIZghVsjJo5/AH5WZpasv8sfrGiiohAxtieoYoJkv5MOYP4/2lPlOY+Cgw1Yoz\n"
-       "+HHv31AllgFsBquBb/kJVmCCNsAOcnvQzTZUsW/TXz9G2nwRdqI1nSy2JvVjZGsq\n"
-       "GQIDAQAB\n"
-       "-----END PUBLIC KEY-----\n";
-}
 
-using namespace CKM;
+constexpr char PASS[] = "password";
 
-BOOST_AUTO_TEST_SUITE(KEY_TEST)
+struct KeyData {
+       KeyType type;
+       bool pass;
+       std::string data;
+};
 
-POSITIVE_TEST_CASE(constructors)
-{
-       RawBuffer keybuf(PUBKEY_PEM.begin(), PUBKEY_PEM.end());
+const KeyData KEYS[] = {
+       {
+               KeyType::KEY_RSA_PRIVATE,
+               false,
+               "-----BEGIN RSA PRIVATE KEY-----\n"
+               "MIICXAIBAAKBgQDMP6sKttnQ58BAi27b8X+8KVQtJgpJhhCF0RtWaTVqAhVDG3y4\n"
+               "x6IuAvXDtPSjLe/2E01fYGVxNComPJOmUOfUD06BCWPYH2+7jOfQIOy/TMlt+W7x\n"
+               "fou9rqnPRoKRaodoLqH5WK0ahkntWCAjstoKZoG+3Op0tEjy0jpmzeyNiQIDAQAB\n"
+               "AoGBAJRDX1CuvNx1bkwsKvQDkTqwMYd4hp0qcVICIbsPMhPaoT6OdHHZkHOf+HDx\n"
+               "KWhOj1LsXgzu95Q+Tp5k+LURI8ayu2RTsz/gYECgPNUsZ7gXl4co1bK+g5kiC+qr\n"
+               "sgSfkbYpp0OXefnl5x4KaJlZeSpn0UdDqx0kwI1x2E098i1VAkEA5thNY9YZNQdN\n"
+               "p6aopxOF5OmAjbLkq6wu255rDM5YgeepXXro/lmPociobtv8vPzbWKfoYZJL0Zj4\n"
+               "Qzj7Qz7s0wJBAOKBbpeG9PuNP1nR1h8kvyuILW8F89JOcIOUeqwokq4eJVqXdFIj\n"
+               "ct8eSEFmyXNqXD7b9+Tcw6vRIZuddVhNcrMCQAlpaD5ZzE1NLu1W7ilhsmPS4Vrl\n"
+               "oE0fiAmMO/EZuKITP+R/zmAQZrrB45whe/x4krjan67auByjj/utpxDmz+ECQEg/\n"
+               "UK80dN/n5dUYgVvdtLyF6zgGhgcGzgyqR5ayOlcfdnq25Htuoy1X02RJDOirfFDw\n"
+               "iNmPMTqUskuYpd1MltECQBwcy1cpnJWIXwCTQwg3enjkOVw80Tbr3iU9ASjHJTH2\n"
+               "N6FGHC4BQCm1fL6Bo0/0oSra+Ika3/1Vw1WwijUSiO8=\n"
+               "-----END RSA PRIVATE KEY-----"
+       },{
+               KeyType::KEY_RSA_PRIVATE,
+               true,
+               "-----BEGIN RSA PRIVATE KEY-----\n"
+               "Proc-Type: 4,ENCRYPTED\n"
+               "DEK-Info: AES-128-CBC,C73D912AE0B2F3AE9DDF4E4ACBA904A6\n"
+               "\n"
+               "Q4jKICSZm6cNDavb1WFWJTKfqyr+XYkXTfpVVtMcJ/34dcLxzqxOzigjiSR7RfeN\n"
+               "0JQHUKJgUHz5eCg4uCwaEBE+WkWzwREsD34bY73fLqqSL9Dpx5/6eHvXNI/zcueP\n"
+               "SZphgUpV4xSUPnlZ3M39NUaDmHmGccdInmsd8AB+StuT/2M2hVUgFQiYKL6XcyFt\n"
+               "xsARQo0IfeSgUV5M7gwxJkwbdlEzENPpRLif8g1yVDGMUefoNiC46mxlvADq9Lt6\n"
+               "fI1FVH5yMeADgTXcW/YJ/1wIY3RspDOXZQK/RlNxjt3KOGUL1h7dD3a4R+8Xwjxi\n"
+               "lk1m8HDFZc35PBBNkEL0qGtRzlWuU1Gpsef4MAJpm6VsdCXDXoeu8be4EsKUXNif\n"
+               "8DyBqaTYmqg6TD3ZtHFqmRq+mv6dYUYBLA6BJvfPwDagUmkju8maXet/fQ+8Xse/\n"
+               "zZFl59pz5jm6d9fxRI+5eWaw6b7gD7nREgpbgToaJHbWw2yrVHkhEs37gtS9DR3O\n"
+               "+a4eOMJMwAspI/RK3K+4QND6ffmCbJH8hroz4PtbBb2war4C+SLN7XoOhcQQK5tU\n"
+               "WBVuJR4CharlRwG5hO7wIBWAdwgpv5IZ/SM9D561ktHLnAhCp66RCjcmAmy7dGVq\n"
+               "KX2g0Iu7yGGALDbdmznrkt6TeaPrSXd3Kn6qZCYLWV8i/XpDknelii2mqlrztPog\n"
+               "K04bvdDXX80vtLyGiG+kmteaT45+nhrl22siOaokxQuiCuZax6pXKFLJDr1n1KIi\n"
+               "O8eHDDfjNrxdjA23KJmfzMbHU+/G65jBomeS6opwMrVfD/ee0rlVCBQxCiNRrnlx\n"
+               "-----END RSA PRIVATE KEY-----\n"
+       },{
+               KeyType::KEY_RSA_PUBLIC,
+               false,
+               "-----BEGIN PUBLIC KEY-----\n"
+               "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMP6sKttnQ58BAi27b8X+8KVQt\n"
+               "JgpJhhCF0RtWaTVqAhVDG3y4x6IuAvXDtPSjLe/2E01fYGVxNComPJOmUOfUD06B\n"
+               "CWPYH2+7jOfQIOy/TMlt+W7xfou9rqnPRoKRaodoLqH5WK0ahkntWCAjstoKZoG+\n"
+               "3Op0tEjy0jpmzeyNiQIDAQAB\n"
+               "-----END PUBLIC KEY-----"
+       },{
+               KeyType::KEY_DSA_PRIVATE,
+               false,
+               "-----BEGIN DSA PRIVATE KEY-----\n"
+               "MIIBuwIBAAKBgQDIsQRYgnU4mm5VrMyykpNNzeHTQAO8E2hJAcOwNPBrdos8amak\n"
+               "rcJnyBaNh56ZslcuXNEKJuxiDsy4VM9KUR8fHTqTiF5s+4NArzdrdwNQpKWjAqJN\n"
+               "fgpCdaLZHw9o857flcQ4dyYNnAz1/SNGnv03Dm8EYRNRFNaFNw7zBPjyVwIVANyj\n"
+               "7ijLfrCbDZDi6ond5Np1Ns0hAoGBAIcS1ceWtw6DAGmYww27r/1lLtqjrq8j0w0a\n"
+               "F6Ly+pZ/y+WTw9KT18eRKPmVgruVSn3VVVJeN00XaoKvfPSHkTRIE5rro2ZEInhp\n"
+               "3g0Vak7EXJWe7KKBRXqSMNFkndjKv1nyNKeWSEq9Xql6SPn8J8TfmbyUpPSIglZR\n"
+               "vJ2DHwHJAoGAPZLRdIhIIJi4UWoyQrCqk1iF3pkBeukXzeZGqNWEjgzLAjMZEVYM\n"
+               "DLLKippahjxLZSWB7LOoS+XE4fonpBBute/tgF23ToR8fQuiBu+KvtAP/QuCOJ/L\n"
+               "S0aYYr1/eXmMByYPZ58Vf93KuUgoUAkWmc+mLBn6J2+fygnWcOOSo6sCFC/slPOv\n"
+               "yAKPlW7WQzgV5jLLNUW7\n"
+               "-----END DSA PRIVATE KEY-----"
+       },{
+               KeyType::KEY_DSA_PRIVATE,
+               true,
+               "-----BEGIN DSA PRIVATE KEY-----\n"
+               "Proc-Type: 4,ENCRYPTED\n"
+               "DEK-Info: AES-128-CBC,048C0CDD71CF9AF8D647C364365C44F1\n"
+               "\n"
+               "lBUAm8XCQ0xoa7P3s8VCRK8Dw0oqDlk2P1Yr9oQZ4zq7eEz4ozocOeANLEsarTrT\n"
+               "IaxrZnuGs+lg6NqEk3UdHCvocJr4TP+jommMYYXCZcX7l0D/CjqJZ/EWb8xrvVqN\n"
+               "Ra+JuZQobFnhDJLC0eHzhuNSZJe2OViEnWEyv3cYvztekzY7ldR3A5MhLScXJ9fZ\n"
+               "Ufabu5ZbJNsNdcZp/kVE6piriANqy2CECGKp7BycVjHRGE44+jpI5TrXoxuaPUsR\n"
+               "cFvaeWRdhUHGjuxiSaDjSn3LR6UenpfYDFKPl5h6TLKcHZLx1kjtiN+Fed4Y7Xzb\n"
+               "Va8OMj/g7AsJmzrl4+qdfgTz0SnbbLAXTpHMg7DBJDM6eNDgXsOeLHoJp4t+50vQ\n"
+               "M4qCmhoUZ5cMiTUpbGQMqwawXORe0JM+Qg/6jdWHnH5zdyYxbqk7wIhPAGMm0Gbd\n"
+               "6bXHutc+AaMVIdqoBvhppeedEUNFVSkoxyglJY3fb24n81Us/r1IUwWL4exWLXsl\n"
+               "DizasdaCWN43k45BJ+It9L6RcKJLwCQpppfPcZBPCavYh4wW93NXVsbpPesDyXwX\n"
+               "87h4JnKOgH5wtt/xforC+g==\n"
+               "-----END DSA PRIVATE KEY-----\n"
+       },{
+               KeyType::KEY_DSA_PUBLIC,
+               false,
+               "-----BEGIN PUBLIC KEY-----\n"
+               "MIIBtzCCASwGByqGSM44BAEwggEfAoGBAMixBFiCdTiablWszLKSk03N4dNAA7wT\n"
+               "aEkBw7A08Gt2izxqZqStwmfIFo2HnpmyVy5c0Qom7GIOzLhUz0pRHx8dOpOIXmz7\n"
+               "g0CvN2t3A1CkpaMCok1+CkJ1otkfD2jznt+VxDh3Jg2cDPX9I0ae/TcObwRhE1EU\n"
+               "1oU3DvME+PJXAhUA3KPuKMt+sJsNkOLqid3k2nU2zSECgYEAhxLVx5a3DoMAaZjD\n"
+               "Dbuv/WUu2qOuryPTDRoXovL6ln/L5ZPD0pPXx5Eo+ZWCu5VKfdVVUl43TRdqgq98\n"
+               "9IeRNEgTmuujZkQieGneDRVqTsRclZ7sooFFepIw0WSd2Mq/WfI0p5ZISr1eqXpI\n"
+               "+fwnxN+ZvJSk9IiCVlG8nYMfAckDgYQAAoGAPZLRdIhIIJi4UWoyQrCqk1iF3pkB\n"
+               "eukXzeZGqNWEjgzLAjMZEVYMDLLKippahjxLZSWB7LOoS+XE4fonpBBute/tgF23\n"
+               "ToR8fQuiBu+KvtAP/QuCOJ/LS0aYYr1/eXmMByYPZ58Vf93KuUgoUAkWmc+mLBn6\n"
+               "J2+fygnWcOOSo6s=\n"
+               "-----END PUBLIC KEY-----"
+       },{
+               KeyType::KEY_ECDSA_PRIVATE,
+               false,
+               "-----BEGIN EC PRIVATE KEY-----\n"
+               "MF8CAQEEGF3rz8OuFpcESrlqCm0G96oovr0XbX+DRKAKBggqhkjOPQMBAaE0AzIA\n"
+               "BHiZYByQiRNQ91GWNnTfoBbp9G8DP9oJYc/cDZlk4lKUpmbvm//RWf1U7ag3tOVy\n"
+               "sQ==\n"
+               "-----END EC PRIVATE KEY-----"
+       },{
+               KeyType::KEY_ECDSA_PRIVATE,
+               true,
+               "-----BEGIN EC PRIVATE KEY-----\n"
+               "Proc-Type: 4,ENCRYPTED\n"
+               "DEK-Info: AES-128-CBC,F9C394444D857C605B9F12265A7F5530\n"
+               "\n"
+               "D5k5JXXUFNytJVxhTOotRRE2/J8Ur9hSMYkIil2uQszpxRD8Pay8GsIEjiO7hi4S\n"
+               "fn2CdmrqKuX7xOa5uaD3hn0fZzKrSASfhKVBb153nWF4r7tvwAa9gIs3dK9379xC\n"
+               "3zZhim3HX6gG9WXdwC4rHRkglEGTMFTf1Okr9A8Uu+hYv2yAd8b8kumLwhXw6vMC\n"
+               "rIH/GTe6jp4l2xEkdBFQ//Xyd/xEmMxP+28mMKEb6tSiLbN2glBxuj6FWgEYZNJS\n"
+               "BVcctKSvXJY4MpsWxso73CFWZJPeOZ/lNicYkPRsGfU=\n"
+               "-----END EC PRIVATE KEY-----"
+       },{
+               KeyType::KEY_ECDSA_PUBLIC,
+               false,
+               "-----BEGIN PUBLIC KEY-----\n"
+               "MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEeJlgHJCJE1D3UZY2dN+gFun0bwM/\n"
+               "2glhz9wNmWTiUpSmZu+b/9FZ/VTtqDe05XKx\n"
+               "-----END PUBLIC KEY-----"
+       }
+};
 
-       KeyImpl key(keybuf);
+void requireKey(const Key& key, KeyType type, int size)
+{
        BOOST_REQUIRE(!key.empty());
+       BOOST_REQUIRE(key.getType() == type);
+       BOOST_REQUIRE(!key.getDER().empty());
+       BOOST_REQUIRE(key.getSize() == size);
+}
+
+void requireKeyImpl(const KeyImpl& key, KeyType type)
+{
+       requireKey(key, type, 0);
 
-       // valid key type case
-       BOOST_REQUIRE(!KeyImpl(key.getEvpShPtr(), KeyType::KEY_RSA_PUBLIC).empty());
+       BOOST_REQUIRE(key.getEvpShPtr());
+
+       if (DataType(type).isKeyPrivate()) {
+               BOOST_REQUIRE(key.getDER() == key.getDERPRV());
+               BOOST_REQUIRE(!key.getDERPRV().empty());
+       } else {
+               BOOST_REQUIRE(key.getDER() == key.getDERPUB());
+       }
 }
 
-NEGATIVE_TEST_CASE(constructors)
+void requireNoKey(const Key& key)
 {
-       RawBuffer keybuf(PUBKEY_PEM.begin(), PUBKEY_PEM.end());
+       BOOST_REQUIRE(key.empty());
+       BOOST_REQUIRE(key.getType() == KeyType::KEY_NONE);
+       BOOST_REQUIRE(key.getDER().empty());
+       BOOST_REQUIRE(key.getSize() == 0);
+}
 
-       KeyImpl key(keybuf);
-       BOOST_REQUIRE(!key.empty());
+void requireNoKeyImpl(const KeyImpl& key)
+{
+       requireNoKey(key);
+       BOOST_REQUIRE(!key.getEvpShPtr());
+       BOOST_REQUIRE(key.getDERPRV().empty());
+       BOOST_REQUIRE(key.getDERPUB().empty());
+}
 
-       // invalid key type cases
-       BOOST_REQUIRE(KeyImpl(key.getEvpShPtr(), KeyType::KEY_DSA_PUBLIC).empty());
-       BOOST_REQUIRE(KeyImpl(key.getEvpShPtr(), KeyType::KEY_DSA_PRIVATE).empty());
-       BOOST_REQUIRE(KeyImpl(key.getEvpShPtr(), KeyType::KEY_ECDSA_PUBLIC).empty());
-       BOOST_REQUIRE(KeyImpl(key.getEvpShPtr(), KeyType::KEY_ECDSA_PRIVATE).empty());
-       BOOST_REQUIRE(KeyImpl(key.getEvpShPtr(), KeyType::KEY_AES).empty());
-       BOOST_REQUIRE(KeyImpl(key.getEvpShPtr(), static_cast<KeyType>(999999)).empty());
+KeyType privateType(KeyType type)
+{
+       switch (type)
+       {
+       case KeyType::KEY_RSA_PUBLIC:
+               return KeyType::KEY_RSA_PRIVATE;
+       case KeyType::KEY_DSA_PUBLIC:
+               return KeyType::KEY_DSA_PRIVATE;
+       case KeyType::KEY_ECDSA_PUBLIC:
+               return KeyType::KEY_ECDSA_PRIVATE;
+       default:
+               return type;
+       }
 }
 
+} // anonymous namespace
+
+BOOST_AUTO_TEST_SUITE(KEY_TEST)
 
-POSITIVE_TEST_CASE(get_size)
+POSITIVE_TEST_CASE(KeyImpl)
 {
-       RawBuffer keybuf(PUBKEY_PEM.begin(), PUBKEY_PEM.end());
+       for (auto& keyInfo : KEYS) {
+               RawBuffer keyBuf(keyInfo.data.begin(), keyInfo.data.end());
 
-       KeyImpl key(keybuf);
-       BOOST_REQUIRE(!key.empty());
+               // PEM
+               KeyImpl keyPem(keyBuf, keyInfo.pass ? PASS : "");
+               requireKeyImpl(keyPem, keyInfo.type);
+
+               // DER
+               KeyImpl keyDer(keyPem.getDER());
+               requireKeyImpl(keyDer, keyInfo.type);
 
-       // not implemented yet but test for coverage. It'll just return 0
-       BOOST_REQUIRE_NO_THROW(key.getSize());
+               // EVP
+               KeyImpl keyEvp(keyPem.getEvpShPtr(), keyInfo.type);
+               requireKeyImpl(keyEvp, keyInfo.type);
+
+               // KeyShPtr
+               auto keyPtr = Key::create(keyBuf, keyInfo.pass ? PASS : "");
+               BOOST_REQUIRE(keyPtr);
+               requireKey(*keyPtr, keyInfo.type, 0);
+       }
 }
 
-BOOST_AUTO_TEST_SUITE_END()
+NEGATIVE_TEST_CASE(KeyImpl)
+{
+       // PEM empty buffer
+       requireNoKeyImpl(KeyImpl(RawBuffer()));
+
+       auto keyPtr = Key::create(RawBuffer());
+       BOOST_REQUIRE(!keyPtr);
+
+       for (auto& keyInfo : KEYS) {
+               RawBuffer keyBuf(keyInfo.data.begin(), keyInfo.data.end());
 
-BOOST_AUTO_TEST_SUITE(AES_KEY_TEST)
+               // PEM
+               if (keyInfo.pass)
+                       requireNoKeyImpl(KeyImpl(keyBuf, "wrong password"));
+               auto keyBuf2 = keyBuf;
+               keyBuf2.resize(keyBuf.size() - 2);
+               requireNoKeyImpl(KeyImpl(keyBuf2, keyInfo.pass ? PASS : ""));
+               KeyImpl keyPem(keyBuf, keyInfo.pass ? PASS : "");
 
-POSITIVE_TEST_CASE(constructors)
+               // DER
+               auto der = keyPem.getDER();
+               der.resize(der.size() - 1);
+               KeyImpl keyDer(der);
+               requireNoKeyImpl(keyDer);
+
+               // EVP
+               requireNoKeyImpl(KeyImpl(KeyImpl::EvpShPtr(), keyInfo.type));
+               for (int i = -1; i <= static_cast<int>(KeyType::KEY_AES) + 1; i++) {
+                       KeyType otherType = static_cast<KeyType>(i);
+                       if (privateType(otherType) == privateType(keyInfo.type))
+                               continue;
+
+                       requireNoKeyImpl(KeyImpl(keyPem.getEvpShPtr(), otherType));
+               }
+
+               // KeyShPtr
+               if (keyInfo.pass)
+                       BOOST_REQUIRE(!Key::create(keyBuf, ""));
+       }
+}
+
+POSITIVE_TEST_CASE(KeyAesImpl)
 {
-       // invalid key size
-       RawBuffer keybuf({0x01, 0x02, 0x03, 0x04});
-       BOOST_REQUIRE(!Key::createAES(keybuf));
-
-       keybuf.clear();
-       for (size_t i = 0; i < 16; ++i)
-               keybuf.push_back(i);
-       BOOST_REQUIRE(Key::createAES(keybuf));
-
-       keybuf.clear();
-       for (size_t i = 0; i < 24; ++i)
-               keybuf.push_back(i);
-       BOOST_REQUIRE(Key::createAES(keybuf));
-
-       keybuf.clear();
-       for (size_t i = 0; i < 32; ++i)
-               keybuf.push_back(i);
-       BOOST_REQUIRE(Key::createAES(keybuf));
+       auto testAes = [](size_t size){
+               auto keyBuf = createRandom(size);
+               auto key = Key::createAES(keyBuf);
+               BOOST_REQUIRE(key);
+               requireKey(*key, KeyType::KEY_AES, size);
+               BOOST_REQUIRE(key->getDER() == keyBuf);
+       };
+
+       testAes(32);
+       testAes(24);
+       testAes(16);
+}
+
+NEGATIVE_TEST_CASE(KeyAesImpl)
+{
+       auto testNoAes = [](size_t size){
+               auto keyBuf = createRandom(size);
+               auto key = Key::createAES(keyBuf);
+               BOOST_REQUIRE(!key);
+               requireNoKey(KeyAESImpl(keyBuf));
+       };
+
+       testNoAes(0);
+       testNoAes(1);
+       testNoAes(8);
+       testNoAes(15);
+       testNoAes(17);
+       testNoAes(33);
+       testNoAes(48);
+       testNoAes(64);
 }
 
 BOOST_AUTO_TEST_SUITE_END()