security: Change the ownership model of Pib and its related entities
Change-Id: I6816a0fd5c7af490f7e98db196e0214219f4b05c
Refs: #3349
diff --git a/src/security/pib/certificate-container.cpp b/src/security/pib/certificate-container.cpp
index fa8d058..e68b0cc 100644
--- a/src/security/pib/certificate-container.cpp
+++ b/src/security/pib/certificate-container.cpp
@@ -21,22 +21,31 @@
#include "certificate-container.hpp"
#include "pib-impl.hpp"
+#include "util/concepts.hpp"
namespace ndn {
namespace security {
namespace pib {
+NDN_CXX_ASSERT_FORWARD_ITERATOR(CertificateContainer::const_iterator);
+
+CertificateContainer::const_iterator::const_iterator()
+ : m_container(nullptr)
+{
+}
+
CertificateContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
- shared_ptr<PibImpl> impl)
+ const CertificateContainer& container)
: m_it(it)
- , m_impl(impl)
+ , m_container(&container)
{
}
v2::Certificate
CertificateContainer::const_iterator::operator*()
{
- return m_impl->getCertificate(*m_it);
+ BOOST_ASSERT(m_container != nullptr);
+ return m_container->get(*m_it);
}
CertificateContainer::const_iterator&
@@ -49,50 +58,52 @@
CertificateContainer::const_iterator
CertificateContainer::const_iterator::operator++(int)
{
- const_iterator it(m_it, m_impl);
+ BOOST_ASSERT(m_container != nullptr);
+ const_iterator it(m_it, *m_container);
++m_it;
return it;
}
bool
-CertificateContainer::const_iterator::operator==(const const_iterator& other)
+CertificateContainer::const_iterator::operator==(const const_iterator& other) const
{
- return (m_impl == other.m_impl && m_it == other.m_it);
+ bool isThisEnd = m_container == nullptr || m_it == m_container->m_certNames.end();
+ bool isOtherEnd = other.m_container == nullptr || other.m_it == other.m_container->m_certNames.end();
+ return ((isThisEnd || isOtherEnd) ?
+ (isThisEnd == isOtherEnd) :
+ m_container->m_impl == other.m_container->m_impl && m_it == other.m_it);
}
bool
-CertificateContainer::const_iterator::operator!=(const const_iterator& other)
+CertificateContainer::const_iterator::operator!=(const const_iterator& other) const
{
return !(*this == other);
}
-CertificateContainer::CertificateContainer()
-{
-}
-
-CertificateContainer::CertificateContainer(std::set<Name>&& certNames,
- shared_ptr<PibImpl> impl)
- : m_certNames(certNames)
+CertificateContainer::CertificateContainer(const Name& keyName, shared_ptr<PibImpl> impl)
+ : m_keyName(keyName)
, m_impl(impl)
{
+ BOOST_ASSERT(impl != nullptr);
+ m_certNames = impl->getCertificatesOfKey(keyName);
}
CertificateContainer::const_iterator
CertificateContainer::begin() const
{
- return const_iterator(m_certNames.begin(), m_impl);
+ return const_iterator(m_certNames.begin(), *this);
}
CertificateContainer::const_iterator
CertificateContainer::end() const
{
- return const_iterator(m_certNames.end(), m_impl);
+ return const_iterator();
}
CertificateContainer::const_iterator
CertificateContainer::find(const Name& certName) const
{
- return const_iterator(m_certNames.find(certName), m_impl);
+ return const_iterator(m_certNames.find(certName), *this);
}
size_t
@@ -101,6 +112,57 @@
return m_certNames.size();
}
+void
+CertificateContainer::add(const v2::Certificate& certificate)
+{
+ if (m_keyName != certificate.getKeyName())
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Certificate name `" + certificate.getKeyName().toUri() + "` "
+ "does not match key name"));
+
+ const Name& certName = certificate.getName();
+ m_certNames.insert(certName);
+ m_certs[certName] = certificate;
+ m_impl->addCertificate(certificate);
+}
+
+void
+CertificateContainer::remove(const Name& certName)
+{
+ if (!v2::Certificate::isValidName(certName) ||
+ v2::extractKeyNameFromCertName(certName) != m_keyName) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Certificate name `" + certName.toUri() + "` "
+ "is invalid or does not match key name"));
+ }
+
+ m_certNames.erase(certName);
+ m_certs.erase(certName);
+ m_impl->removeCertificate(certName);
+}
+
+v2::Certificate
+CertificateContainer::get(const Name& certName) const
+{
+ auto it = m_certs.find(certName);
+
+ if (it != m_certs.end())
+ return it->second;
+
+ if (!v2::Certificate::isValidName(certName) ||
+ v2::extractKeyNameFromCertName(certName) != m_keyName) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Certificate name `" + certName.toUri() + "` "
+ "is invalid or does not match key name"));
+ }
+
+ m_certs[certName] = m_impl->getCertificate(certName);
+ return m_certs[certName];
+}
+
+bool
+CertificateContainer::isConsistent() const
+{
+ return m_certNames == m_impl->getCertificatesOfKey(m_keyName);
+}
+
} // namespace pib
} // namespace security
} // namespace ndn
diff --git a/src/security/pib/certificate-container.hpp b/src/security/pib/certificate-container.hpp
index eba765e..42e9534 100644
--- a/src/security/pib/certificate-container.hpp
+++ b/src/security/pib/certificate-container.hpp
@@ -23,6 +23,7 @@
#define NDN_SECURITY_PIB_CERTIFICATE_CONTAINER_HPP
#include <set>
+#include <unordered_map>
#include "../v2/certificate.hpp"
namespace ndn {
@@ -31,16 +32,24 @@
class PibImpl;
-/// @brief A handler to search or enumerate certificates of a key.
-class CertificateContainer
+namespace detail {
+class KeyImpl;
+} // namespace detail
+
+/**
+ * @brief Container of certificates of a key
+ *
+ * The container is used to search/enumerate certificates of a key.
+ * The container can be created only by detail::KeyImpl.
+ */
+class CertificateContainer : noncopyable
{
public:
- class const_iterator
+ class const_iterator : public std::iterator<std::forward_iterator_tag, const v2::Certificate>
{
public:
- friend class CertificateContainer;
+ const_iterator();
- public:
v2::Certificate
operator*();
@@ -51,26 +60,24 @@
operator++(int);
bool
- operator==(const const_iterator& other);
+ operator==(const const_iterator& other) const;
bool
- operator!=(const const_iterator& other);
+ operator!=(const const_iterator& other) const;
private:
- const_iterator(std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+ const_iterator(std::set<Name>::const_iterator it, const CertificateContainer& container);
private:
std::set<Name>::const_iterator m_it;
- shared_ptr<PibImpl> m_impl;
+ const CertificateContainer* m_container;
+
+ friend class CertificateContainer;
};
typedef const_iterator iterator;
public:
- CertificateContainer();
-
- CertificateContainer(std::set<Name>&& certNames, shared_ptr<PibImpl> impl);
-
const_iterator
begin() const;
@@ -83,9 +90,64 @@
size_t
size() const;
+ /**
+ * @brief Add @p certificate into the container
+ * @throw std::invalid_argument the name of @p certificate does not match the key name
+ */
+ void
+ add(const v2::Certificate& certificate);
+
+ /**
+ * @brief Remove a certificate with @p certName from the container
+ * @throw std::invalid_argument @p certName does not match the key name
+ */
+ void
+ remove(const Name& certName);
+
+ /**
+ * @brief Get a certificate with @p certName from the container
+ * @throw std::invalid_argument @p certName does not match the key name
+ * @throw Pib::Error the certificate does not exist
+ */
+ v2::Certificate
+ get(const Name& certName) const;
+
+ /**
+ * @brief Check if the container is consistent with the backend storage
+ *
+ * @note this method is heavyweight and should be used in debugging mode only.
+ */
+ bool
+ isConsistent() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Create certificate container for a key with @p keyName
+ * @param impl The PIB backend implementation.
+ */
+ CertificateContainer(const Name& keyName, shared_ptr<PibImpl> impl);
+
+ const std::set<Name>&
+ getCertNames() const
+ {
+ return m_certNames;
+ }
+
+ const std::unordered_map<Name, v2::Certificate>&
+ getCache() const
+ {
+ return m_certs;
+ }
+
private:
+ Name m_keyName;
std::set<Name> m_certNames;
+ /// @brief Cache of loaded certificates
+ mutable std::unordered_map<Name, v2::Certificate> m_certs;
+
shared_ptr<PibImpl> m_impl;
+
+ friend class detail::KeyImpl;
};
} // namespace pib
diff --git a/src/security/pib/detail/identity-impl.cpp b/src/security/pib/detail/identity-impl.cpp
new file mode 100644
index 0000000..af01dc5
--- /dev/null
+++ b/src/security/pib/detail/identity-impl.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "identity-impl.hpp"
+#include "../pib-impl.hpp"
+#include "../pib.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+
+IdentityImpl::IdentityImpl(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit)
+ : m_name(identityName)
+ , m_isDefaultKeyLoaded(false)
+ , m_keys(identityName, impl)
+ , m_impl(impl)
+{
+ BOOST_ASSERT(impl != nullptr);
+
+ if (needInit) {
+ m_impl->addIdentity(m_name);
+ }
+ else if (!m_impl->hasIdentity(m_name)) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Identity " + m_name.toUri() + " does not exist"));
+ }
+}
+
+Key
+IdentityImpl::addKey(const uint8_t* key, size_t keyLen, const Name& keyName)
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ if (m_keys.find(keyName) != m_keys.end()) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Cannot overwrite existing key " + keyName.toUri()));
+ }
+
+ return m_keys.add(key, keyLen, keyName);
+}
+
+void
+IdentityImpl::removeKey(const Name& keyName)
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ if (m_isDefaultKeyLoaded && m_defaultKey.getName() == keyName)
+ m_isDefaultKeyLoaded = false;
+
+ m_keys.remove(keyName);
+}
+
+Key
+IdentityImpl::getKey(const Name& keyName) const
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ return m_keys.get(keyName);
+}
+
+const KeyContainer&
+IdentityImpl::getKeys() const
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ return m_keys;
+}
+
+const Key&
+IdentityImpl::setDefaultKey(const Name& keyName)
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ m_defaultKey = m_keys.get(keyName);
+ m_isDefaultKeyLoaded = true;
+ m_impl->setDefaultKeyOfIdentity(m_name, keyName);
+ return m_defaultKey;
+}
+
+const Key&
+IdentityImpl::setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName)
+{
+ addKey(key, keyLen, keyName);
+ return setDefaultKey(keyName);
+}
+
+const Key&
+IdentityImpl::getDefaultKey() const
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ if (!m_isDefaultKeyLoaded) {
+ m_defaultKey = m_keys.get(m_impl->getDefaultKeyOfIdentity(m_name));
+ m_isDefaultKeyLoaded = true;
+ }
+
+ BOOST_ASSERT(m_impl->getDefaultKeyOfIdentity(m_name) == m_defaultKey.getName());
+
+ return m_defaultKey;
+}
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/detail/identity-impl.hpp b/src/security/pib/detail/identity-impl.hpp
new file mode 100644
index 0000000..b654348
--- /dev/null
+++ b/src/security/pib/detail/identity-impl.hpp
@@ -0,0 +1,138 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_DETAIL_IDENTITY_IMPL_HPP
+#define NDN_SECURITY_PIB_DETAIL_IDENTITY_IMPL_HPP
+
+#include "../key-container.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+
+class PibImpl;
+
+namespace detail {
+
+/**
+ * @brief Backend instance of Identity
+ *
+ * An Identity has only one backend instance, but may have multiple frontend handles.
+ * Each frontend handle is associated with the only one backend IdentityImpl.
+ *
+ * @throw PibImpl::Error when underlying implementation has non-semantic error.
+ */
+class IdentityImpl : noncopyable
+{
+public:
+ /**
+ * @brief Create an Identity with @p identityName.
+ *
+ * @param identityName The name of the Identity.
+ * @param impl The PIB backend implementation.
+ * @param needInit If true, create the identity in backend when the identity does not exist.
+ * Otherwise, throw Pib::Error when the identity does not exist.
+ */
+ IdentityImpl(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit = false);
+
+ /// @brief Get the name of the identity.
+ const Name&
+ getName() const
+ {
+ return m_name;
+ }
+
+ /**
+ * @brief Add a @p key of @p keyLen bytes with @p keyName (in PKCS#8 format).
+ *
+ * If no default key is set before, the new key will be set as the default key of the identity.
+ *
+ * @return the added key.
+ * @throw std::invalid_argument key name does not match identity
+ * @throw Pib::Error a key with the same name already exists
+ */
+ Key
+ addKey(const uint8_t* key, size_t keyLen, const Name& keyName);
+
+ /**
+ * @brief Remove a key with @p keyName
+ * @throw std::invalid_argument @p keyName does not match identity
+ */
+ void
+ removeKey(const Name& keyName);
+
+ /**
+ * @brief Get a key with id @p keyName.
+ *
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
+ */
+ Key
+ getKey(const Name& keyName) const;
+
+ /**
+ * @brief Get all keys for this Identity.
+ */
+ const KeyContainer&
+ getKeys() const;
+
+ /**
+ * @brief Set the key with id @p keyName.
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
+ * @return The default key
+ */
+ const Key&
+ setDefaultKey(const Name& keyName);
+
+ /**
+ * @brief Add @p key of @p keyLen bytes with @p keyName and set it as the default key
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key with the same name already exists
+ * @return the default key
+ */
+ const Key&
+ setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName);
+
+ /**
+ * @brief Get the default key for this Identity.
+ * @throw Pib::Error the default key does not exist.
+ */
+ const Key&
+ getDefaultKey() const;
+
+private:
+ Name m_name;
+
+ mutable bool m_isDefaultKeyLoaded;
+ mutable Key m_defaultKey;
+
+ mutable KeyContainer m_keys;
+
+ shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_DETAIL_IDENTITY_IMPL_HPP
diff --git a/src/security/pib/detail/key-impl.cpp b/src/security/pib/detail/key-impl.cpp
new file mode 100644
index 0000000..35a0de6
--- /dev/null
+++ b/src/security/pib/detail/key-impl.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "key-impl.hpp"
+#include "../pib-impl.hpp"
+#include "../pib.hpp"
+#include "../../transform/public-key.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+
+KeyImpl::KeyImpl(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl)
+ : m_identity(v2::extractIdentityFromKeyName(keyName))
+ , m_keyName(keyName)
+ , m_key(key, keyLen)
+ , m_isDefaultCertificateLoaded(false)
+ , m_certificates(keyName, impl)
+ , m_impl(impl)
+{
+ BOOST_ASSERT(impl != nullptr);
+
+ if (m_impl->hasKey(m_keyName)) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Cannot overwrite existing key " + m_keyName.toUri()));
+ }
+
+ transform::PublicKey publicKey;
+ try {
+ publicKey.loadPkcs8(key, keyLen);
+ }
+ catch (transform::PublicKey::Error&) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid key bits"));
+ }
+ m_keyType = publicKey.getKeyType();
+
+ m_impl->addKey(m_identity, m_keyName, key, keyLen);
+}
+
+KeyImpl::KeyImpl(const Name& keyName, shared_ptr<PibImpl> impl)
+ : m_identity(v2::extractIdentityFromKeyName(keyName))
+ , m_keyName(keyName)
+ , m_isDefaultCertificateLoaded(false)
+ , m_certificates(keyName, impl)
+ , m_impl(impl)
+{
+ BOOST_ASSERT(impl != nullptr);
+
+ m_key = m_impl->getKeyBits(m_keyName);
+
+ transform::PublicKey key;
+ key.loadPkcs8(m_key.buf(), m_key.size());
+ m_keyType = key.getKeyType();
+}
+
+void
+KeyImpl::addCertificate(const v2::Certificate& certificate)
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ if (m_certificates.find(certificate.getName()) != m_certificates.end()) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Cannot overwrite existing certificate " + certificate.getName().toUri()));
+ }
+
+ m_certificates.add(certificate);
+}
+
+void
+KeyImpl::removeCertificate(const Name& certName)
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ if (m_isDefaultCertificateLoaded && m_defaultCertificate.getName() == certName)
+ m_isDefaultCertificateLoaded = false;
+
+ m_certificates.remove(certName);
+}
+
+v2::Certificate
+KeyImpl::getCertificate(const Name& certName) const
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ return m_certificates.get(certName);
+}
+
+const CertificateContainer&
+KeyImpl::getCertificates() const
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ return m_certificates;
+}
+
+const v2::Certificate&
+KeyImpl::setDefaultCertificate(const Name& certName)
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ m_defaultCertificate = m_certificates.get(certName);
+ m_impl->setDefaultCertificateOfKey(m_keyName, certName);
+ m_isDefaultCertificateLoaded = true;
+ return m_defaultCertificate;
+}
+
+const v2::Certificate&
+KeyImpl::setDefaultCertificate(const v2::Certificate& certificate)
+{
+ addCertificate(certificate);
+ return setDefaultCertificate(certificate.getName());
+}
+
+const v2::Certificate&
+KeyImpl::getDefaultCertificate() const
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ if (!m_isDefaultCertificateLoaded) {
+ m_defaultCertificate = m_impl->getDefaultCertificateOfKey(m_keyName);
+ m_isDefaultCertificateLoaded = true;
+ }
+
+ BOOST_ASSERT(m_impl->getDefaultCertificateOfKey(m_keyName).wireEncode() == m_defaultCertificate.wireEncode());
+
+ return m_defaultCertificate;
+}
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/detail/key-impl.hpp b/src/security/pib/detail/key-impl.hpp
new file mode 100644
index 0000000..c05e77e
--- /dev/null
+++ b/src/security/pib/detail/key-impl.hpp
@@ -0,0 +1,179 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_DETAIL_KEY_IMPL_HPP
+#define NDN_SECURITY_PIB_DETAIL_KEY_IMPL_HPP
+
+#include "../../../data.hpp"
+#include "../certificate-container.hpp"
+#include "../../security-common.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+
+class PibImpl;
+
+namespace detail {
+
+/**
+ * @brief Backend instance of Key
+ *
+ * An Key has only one backend instance, but may have multiple frontend handles.
+ * Each frontend handle is associated with the only one backend KeyImpl.
+ *
+ * @throw PibImpl::Error when underlying implementation has non-semantic error.
+ */
+class KeyImpl : noncopyable
+{
+public:
+ /**
+ * @brief Create a KeyImpl with @p keyName.
+ *
+ * If the key does not exist in the backend, create it in backend.
+ *
+ * @param keyName The name of the key.
+ * @param key The public key to add.
+ * @param keyLen The length of the key.
+ * @param impl The Pib backend implementation.
+ * @throw Pib::Error a key with the same @p keyName already exists.
+ */
+ KeyImpl(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl);
+
+ /**
+ * @brief Create a KeyImpl with @p keyName.
+ *
+ * @param keyName The name of the key.
+ * @param impl The Pib backend implementation.
+ * @throw Pib::Error the key does not exist.
+ */
+ KeyImpl(const Name& keyName, shared_ptr<PibImpl> impl);
+
+ /// @brief Get the name of the key.
+ const Name&
+ getName() const
+ {
+ return m_keyName;
+ }
+
+ /**
+ * @brief Get the name of the belonging identity.
+ */
+ const Name&
+ getIdentity() const
+ {
+ return m_identity;
+ }
+
+ /**
+ * @brief Get key type
+ */
+ KeyType
+ getKeyType() const
+ {
+ return m_keyType;
+ }
+
+ /**
+ * @brief Get public key bits
+ */
+ const Buffer&
+ getPublicKey() const
+ {
+ return m_key;
+ }
+
+ /**
+ * @brief Add @p certificate.
+ *
+ * If no default certificate is set before, the new certificate will be set as the default
+ * certificate of the key.
+ *
+ * @throw std::invalid_argument certificate name does not match key name
+ * @throw Pib::Error a certificate with the same name already exists
+ */
+ void
+ addCertificate(const v2::Certificate& certificate);
+
+ /**
+ * @brief Remove a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
+ */
+ void
+ removeCertificate(const Name& certName);
+
+ /**
+ * @brief Get a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
+ */
+ v2::Certificate
+ getCertificate(const Name& certName) const;
+
+ /// @brief Get all the certificates for this key.
+ const CertificateContainer&
+ getCertificates() const;
+
+ /**
+ * @brief Set an existing one with @p certName as the default certificate
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
+ * @return the default certificate
+ */
+ const v2::Certificate&
+ setDefaultCertificate(const Name& certName);
+
+ /**
+ * @brief Add @p certificate and set it as the default certificate of the key
+ * @throw std::invalid_argument @p certificate does not match key name
+ * @throw Pib::Error the certificate with the same name already exists.
+ * @return the default certificate
+ */
+ const v2::Certificate&
+ setDefaultCertificate(const v2::Certificate& certificate);
+
+ /**
+ * @brief Get the default certificate for this Key.
+ * @throw Pib::Error the default certificate does not exist.
+ */
+ const v2::Certificate&
+ getDefaultCertificate() const;
+
+private:
+ Name m_identity;
+ Name m_keyName;
+ Buffer m_key;
+ KeyType m_keyType;
+
+ mutable bool m_isDefaultCertificateLoaded;
+ mutable v2::Certificate m_defaultCertificate;
+
+ CertificateContainer m_certificates;
+
+ shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_DETAIL_KEY_IMPL_HPP
diff --git a/src/security/pib/identity-container.cpp b/src/security/pib/identity-container.cpp
index 77076af..7c018ce 100644
--- a/src/security/pib/identity-container.cpp
+++ b/src/security/pib/identity-container.cpp
@@ -21,22 +21,32 @@
#include "identity-container.hpp"
#include "pib-impl.hpp"
+#include "detail/identity-impl.hpp"
+#include "util/concepts.hpp"
namespace ndn {
namespace security {
namespace pib {
+NDN_CXX_ASSERT_FORWARD_ITERATOR(IdentityContainer::const_iterator);
+
+IdentityContainer::const_iterator::const_iterator()
+ : m_container(nullptr)
+{
+}
+
IdentityContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
- shared_ptr<PibImpl> impl)
+ const IdentityContainer& container)
: m_it(it)
- , m_impl(impl)
+ , m_container(&container)
{
}
Identity
IdentityContainer::const_iterator::operator*()
{
- return Identity(*m_it, m_impl);
+ BOOST_ASSERT(m_container != nullptr);
+ return m_container->get(*m_it);
}
IdentityContainer::const_iterator&
@@ -57,7 +67,11 @@
bool
IdentityContainer::const_iterator::operator==(const const_iterator& other)
{
- return (m_impl == other.m_impl && m_it == other.m_it);
+ bool isThisEnd = m_container == nullptr || m_it == m_container->m_identityNames.end();
+ bool isOtherEnd = other.m_container == nullptr || other.m_it == other.m_container->m_identityNames.end();
+ return ((isThisEnd || isOtherEnd) ?
+ (isThisEnd == isOtherEnd) :
+ m_container->m_pibImpl == other.m_container->m_pibImpl && m_it == other.m_it);
}
bool
@@ -66,39 +80,83 @@
return !(*this == other);
}
-IdentityContainer::IdentityContainer()
+IdentityContainer::IdentityContainer(shared_ptr<PibImpl> pibImpl)
+ : m_pibImpl(pibImpl)
{
-}
-
-IdentityContainer::IdentityContainer(std::set<Name>&& identities,
- shared_ptr<PibImpl> impl)
- : m_identities(identities)
- , m_impl(impl)
-{
+ BOOST_ASSERT(pibImpl != nullptr);
+ m_identityNames = pibImpl->getIdentities();
}
IdentityContainer::const_iterator
IdentityContainer::begin() const
{
- return const_iterator(m_identities.begin(), m_impl);
+ return const_iterator(m_identityNames.begin(), *this);
}
IdentityContainer::const_iterator
IdentityContainer::end() const
{
- return const_iterator(m_identities.end(), m_impl);
+ return const_iterator();
}
IdentityContainer::const_iterator
IdentityContainer::find(const Name& identity) const
{
- return const_iterator(m_identities.find(identity), m_impl);
+ return const_iterator(m_identityNames.find(identity), *this);
}
size_t
IdentityContainer::size() const
{
- return m_identities.size();
+ return m_identityNames.size();
+}
+
+Identity
+IdentityContainer::add(const Name& identityName)
+{
+ if (m_identityNames.count(identityName) == 0) {
+ m_identityNames.insert(identityName);
+ m_identities[identityName] =
+ shared_ptr<detail::IdentityImpl>(new detail::IdentityImpl(identityName, m_pibImpl, true));
+ }
+ return get(identityName);
+}
+
+void
+IdentityContainer::remove(const Name& identityName)
+{
+ m_identityNames.erase(identityName);
+ m_identities.erase(identityName);
+ m_pibImpl->removeIdentity(identityName);
+}
+
+Identity
+IdentityContainer::get(const Name& identityName) const
+{
+ shared_ptr<detail::IdentityImpl> id;
+ auto it = m_identities.find(identityName);
+
+ if (it != m_identities.end()) {
+ id = it->second;
+ }
+ else {
+ id = shared_ptr<detail::IdentityImpl>(new detail::IdentityImpl(identityName, m_pibImpl, false));
+ m_identities[identityName] = id;
+ }
+ return Identity(id);
+}
+
+void
+IdentityContainer::reset()
+{
+ m_identities.clear();
+ m_identityNames = m_pibImpl->getIdentities();
+}
+
+bool
+IdentityContainer::isConsistent() const
+{
+ return m_identityNames == m_pibImpl->getIdentities();
}
} // namespace pib
diff --git a/src/security/pib/identity-container.hpp b/src/security/pib/identity-container.hpp
index 1ac30e1..94cd370 100644
--- a/src/security/pib/identity-container.hpp
+++ b/src/security/pib/identity-container.hpp
@@ -22,25 +22,35 @@
#ifndef NDN_SECURITY_PIB_IDENTITY_CONTAINER_HPP
#define NDN_SECURITY_PIB_IDENTITY_CONTAINER_HPP
-#include <set>
#include "identity.hpp"
+#include <set>
+#include <unordered_map>
+
namespace ndn {
namespace security {
namespace pib {
class PibImpl;
-/// @brief A handler to search or enumerate identities in PIB.
-class IdentityContainer
+namespace detail {
+class IdentityImpl;
+} // namespace detail
+
+/**
+ * @brief Container of identities of a Pib
+ *
+ * The container is used to search/enumerate identities of a Pib.
+ * The container can be created only by Pib.
+ */
+class IdentityContainer : noncopyable
{
public:
- class const_iterator
+ class const_iterator : public std::iterator<std::forward_iterator_tag, const Identity>
{
public:
- friend class IdentityContainer;
+ const_iterator();
- public:
Identity
operator*();
@@ -57,21 +67,18 @@
operator!=(const const_iterator& other);
private:
- const_iterator(std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+ const_iterator(std::set<Name>::const_iterator it, const IdentityContainer& container);
private:
- Name m_identity;
std::set<Name>::const_iterator m_it;
- shared_ptr<PibImpl> m_impl;
+ const IdentityContainer* m_container;
+
+ friend class IdentityContainer;
};
typedef const_iterator iterator;
public:
- IdentityContainer();
-
- IdentityContainer(std::set<Name>&& identities, shared_ptr<PibImpl> impl);
-
const_iterator
begin() const;
@@ -84,9 +91,69 @@
size_t
size() const;
+ /**
+ * @brief Add @p identity into the container
+ */
+ Identity
+ add(const Name& identityName);
+
+ /**
+ * @brief Remove @p identity from the container
+ */
+ void
+ remove(const Name& identity);
+
+ /**
+ * @brief Get @p identity from the container
+ * @throw Pib::Error @p identity does not exist
+ */
+ Identity
+ get(const Name& identity) const;
+
+ /**
+ * @brief Reset state of the container
+ *
+ * This method removes all loaded identities and retrieves identity names from the PIB
+ * implementation.
+ */
+ void
+ reset();
+
+ /**
+ * @brief Check if the container is consistent with the backend storage
+ *
+ * @note this method is heavyweight and should be used in debugging mode only.
+ */
+ bool
+ isConsistent() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Create identity container
+ * @param impl The PIB backend implementation.
+ */
+ explicit
+ IdentityContainer(shared_ptr<PibImpl> pibImpl);
+
+ const std::set<Name>&
+ getIdentityNames() const
+ {
+ return m_identityNames;
+ }
+
+ const std::unordered_map<Name, shared_ptr<detail::IdentityImpl>>&
+ getLoadedIdentities() const
+ {
+ return m_identities;
+ }
+
private:
- std::set<Name> m_identities;
- shared_ptr<PibImpl> m_impl;
+ std::set<Name> m_identityNames;
+ /// @brief Cache of loaded detail::IdentityImpl.
+ mutable std::unordered_map<Name, shared_ptr<detail::IdentityImpl>> m_identities;
+
+ shared_ptr<PibImpl> m_pibImpl;
+ friend class Pib;
};
} // namespace pib
diff --git a/src/security/pib/identity.cpp b/src/security/pib/identity.cpp
index 11cad88..4797cb6 100644
--- a/src/security/pib/identity.cpp
+++ b/src/security/pib/identity.cpp
@@ -20,123 +20,65 @@
*/
#include "identity.hpp"
-#include "pib-impl.hpp"
-#include "pib.hpp"
+#include "detail/identity-impl.hpp"
namespace ndn {
namespace security {
namespace pib {
-Identity::Identity()
- : m_hasDefaultKey(false)
- , m_needRefreshKeys(false)
- , m_impl(nullptr)
-{
-}
+Identity::Identity() = default;
-Identity::Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit)
- : m_name(identityName)
- , m_hasDefaultKey(false)
- , m_needRefreshKeys(true)
- , m_impl(impl)
+Identity::Identity(weak_ptr<detail::IdentityImpl> impl)
+ : m_impl(impl)
{
- validityCheck();
-
- if (needInit)
- m_impl->addIdentity(m_name);
- else if (!m_impl->hasIdentity(m_name))
- BOOST_THROW_EXCEPTION(Pib::Error("Identity: " + m_name.toUri() + " does not exist"));
}
const Name&
Identity::getName() const
{
- return m_name;
+ return lock()->getName();
}
Key
Identity::addKey(const uint8_t* key, size_t keyLen, const Name& keyName)
{
- if (m_name != v2::extractIdentityFromKeyName(keyName)) {
- BOOST_THROW_EXCEPTION(Pib::Error("Key name `" + keyName.toUri() + "` does not match identity "
- "`" + m_name.toUri() + "`"));
- }
-
- // if we have already loaded all the keys, but the new key is not one of them the
- // KeyContainer should be refreshed
- m_needRefreshKeys = m_needRefreshKeys || m_keys.find(keyName) == m_keys.end();
-
- return Key(keyName, key, keyLen, m_impl);
+ return lock()->addKey(key, keyLen, keyName);
}
void
Identity::removeKey(const Name& keyName)
{
- if (m_name != v2::extractIdentityFromKeyName(keyName)) {
- BOOST_THROW_EXCEPTION(Pib::Error("Key name `" + keyName.toUri() + "` does not match identity "
- "`" + m_name.toUri() + "`"));
- }
-
- validityCheck();
-
- if (m_hasDefaultKey && m_defaultKey.getName() == keyName)
- m_hasDefaultKey = false;
-
- m_impl->removeKey(keyName);
- m_needRefreshKeys = true;
+ return lock()->removeKey(keyName);
}
Key
Identity::getKey(const Name& keyName) const
{
- return Key(keyName, m_impl);
+ return lock()->getKey(keyName);
}
const KeyContainer&
Identity::getKeys() const
{
- validityCheck();
-
- if (m_needRefreshKeys) {
- m_keys = KeyContainer(m_name, m_impl->getKeysOfIdentity(m_name), m_impl);
- m_needRefreshKeys = false;
- }
-
- return m_keys;
+ return lock()->getKeys();
}
-Key&
+const Key&
Identity::setDefaultKey(const Name& keyName)
{
- validityCheck();
-
- m_defaultKey = Key(keyName, m_impl);
- m_hasDefaultKey = true;
-
- m_impl->setDefaultKeyOfIdentity(m_name, keyName);
- return m_defaultKey;
+ return lock()->setDefaultKey(keyName);
}
-Key&
+const Key&
Identity::setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName)
{
- validityCheck();
-
- addKey(key, keyLen, keyName);
- return setDefaultKey(keyName);
+ return lock()->setDefaultKey(key, keyLen, keyName);
}
-Key&
+const Key&
Identity::getDefaultKey() const
{
- validityCheck();
-
- if (!m_hasDefaultKey) {
- m_defaultKey = Key(m_impl->getDefaultKeyOfIdentity(m_name), m_impl);
- m_hasDefaultKey = true;
- }
-
- return m_defaultKey;
+ return lock()->getDefaultKey();
}
Identity::operator bool() const
@@ -147,15 +89,18 @@
bool
Identity::operator!() const
{
- return (m_impl == nullptr);
+ return m_impl.expired();
}
-void
-Identity::validityCheck() const
+shared_ptr<detail::IdentityImpl>
+Identity::lock() const
{
- if (m_impl == nullptr) {
- BOOST_THROW_EXCEPTION(std::domain_error("Invalid identity instance"));
- }
+ auto impl = m_impl.lock();
+
+ if (impl == nullptr)
+ BOOST_THROW_EXCEPTION(std::domain_error("Invalid Identity instance"));
+
+ return impl;
}
} // namespace pib
diff --git a/src/security/pib/identity.hpp b/src/security/pib/identity.hpp
index 0a6ca60..3d0117d 100644
--- a/src/security/pib/identity.hpp
+++ b/src/security/pib/identity.hpp
@@ -28,14 +28,16 @@
namespace security {
namespace pib {
+namespace detail {
+class IdentityImpl;
+} // namespace detail
+
/**
- * @brief represents an identity
+ * @brief A frontend handle of an Identity
*
* Identity is at the top level in PIB's Identity-Key-Certificate hierarchy. An identity has a
* Name, and contains zero or more keys, at most one of which is set as the default key of this
* identity. Properties of a key can be accessed after obtaining a Key object.
- *
- * @throw Pib::Error when underlying implementation has non-semantic error.
*/
class Identity
{
@@ -44,7 +46,7 @@
* @brief Default Constructor
*
* Identity created using this default constructor is just a place holder.
- * It must obtain an actual instance from Pib::getIdentity(...). A typical
+ * It can obtain an actual instance from Pib::getIdentity(...). A typical
* usage would be for exception handling:
*
* Identity id;
@@ -61,105 +63,97 @@
Identity();
/**
- * @brief Create an Identity with @p identityName.
+ * @brief Create an Identity with a backend implementation @p impl.
*
- * @param identityName The name of the Identity.
- * @param impl The backend implementation.
- * @param needInit If true, create the identity in backend when the identity does not exist.
- * Otherwise, throw Pib::Error when the identity does not exist.
+ * This method should only be used by IdentityContainer.
*/
- Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit = false);
+ explicit
+ Identity(weak_ptr<detail::IdentityImpl> impl);
- /// @brief Get the name of the identity.
+ /**
+ * @brief Get the name of the identity.
+ */
const Name&
getName() const;
/**
- * @brief Get a key with @p keyName.
- * @throw Pib::Error if the key does not exist.
+ * @brief Get a key with id @p keyName.
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
*/
Key
getKey(const Name& keyName) const;
- /// @brief Get all the keys for this Identity.
+ /**
+ * @brief Get all keys for this identity.
+ */
const KeyContainer&
getKeys() const;
/**
* @brief Get the default key for this Identity.
- *
- * @throws Pib::Error if the default key does not exist.
+ * @throw Pib::Error the default key does not exist.
*/
- Key&
+ const Key&
getDefaultKey() const;
- /// @brief Check if the Identity instance is valid
+ /*
+ * @return True if the identity instance is valid
+ */
operator bool() const;
- /// @brief Check if the Identity instance is invalid
+ /**
+ * @return True if the identity instance is invalid
+ */
bool
operator!() const;
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
/**
- * @brief Add a @p key (in PKCS#8 format) with @p keyName.
- *
- * If the key already exists, do nothing.
- *
- * If no default key is set before, the new key will be set as the default key of the identity.
- *
- * @return the added key or existing key with the same key id.
+ * @brief Add a @p key of @p keyLen bytes (in PKCS#8 format) with @p keyName.
+ * @return the handle of added key
+ * @throw std::invalid_argument key name does not match identity
+ * @throw Pib::Error a key with the same name already exists
*/
Key
addKey(const uint8_t* key, size_t keyLen, const Name& keyName);
/**
* @brief Remove a key with @p keyName
+ * @throw std::invalid_argument @p keyName does not match identity
*/
void
removeKey(const Name& keyName);
/**
- * @brief Set the key with id @p keyName.
- *
+ * @brief Set an existing key with @p keyName as the default key.
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
* @return The default key
- * @throws Pib::Error if the key does not exist.
*/
- Key&
+ const Key&
setDefaultKey(const Name& keyName);
/**
- * @brief Set the default key with @p keyName (in PKCS#8 format).
- *
- * If the key does not exist, add the key and set it as the default of the Identity.
- * If the key exists, simply set it as the default key of the Identity.
- *
- * @param key The public key to add.
- * @param keyLen The length of the key.
+ * @brief Add a @p key of @p keyLen bytes with @p keyName and set it as the default key
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key with the same name already exists.
* @return the default key
*/
- Key&
+ const Key&
setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName);
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+private:
/**
- * @brief Check the validity of this instance
- *
- * @throws std::domain_error if the instance is invalid
+ * @brief Check the validity of the instance
+ * @return a shared_ptr when the instance is valid
+ * @throw std::domain_error the instance is invalid
*/
- void
- validityCheck() const;
+ shared_ptr<detail::IdentityImpl>
+ lock() const;
private:
- Name m_name;
-
- mutable bool m_hasDefaultKey;
- mutable Key m_defaultKey;
-
- mutable bool m_needRefreshKeys;
- mutable KeyContainer m_keys;
-
- shared_ptr<PibImpl> m_impl;
+ weak_ptr<detail::IdentityImpl> m_impl;
};
} // namespace pib
diff --git a/src/security/pib/key-container.cpp b/src/security/pib/key-container.cpp
index 7653955..34f96d0 100644
--- a/src/security/pib/key-container.cpp
+++ b/src/security/pib/key-container.cpp
@@ -21,24 +21,32 @@
#include "key-container.hpp"
#include "pib-impl.hpp"
+#include "detail/key-impl.hpp"
+#include "util/concepts.hpp"
namespace ndn {
namespace security {
namespace pib {
-KeyContainer::const_iterator::const_iterator(const Name& identity,
- std::set<Name>::const_iterator it,
- shared_ptr<PibImpl> impl)
- : m_identity(identity)
- , m_it(it)
- , m_impl(impl)
+NDN_CXX_ASSERT_FORWARD_ITERATOR(KeyContainer::const_iterator);
+
+KeyContainer::const_iterator::const_iterator()
+ : m_container(nullptr)
+{
+}
+
+KeyContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
+ const KeyContainer& container)
+ : m_it(it)
+ , m_container(&container)
{
}
Key
KeyContainer::const_iterator::operator*()
{
- return Key(*m_it, m_impl);
+ BOOST_ASSERT(m_container != nullptr);
+ return m_container->get(*m_it);
}
KeyContainer::const_iterator&
@@ -59,7 +67,11 @@
bool
KeyContainer::const_iterator::operator==(const const_iterator& other)
{
- return (m_impl == other.m_impl && m_identity == other.m_identity && m_it == other.m_it);
+ bool isThisEnd = m_container == nullptr || m_it == m_container->m_keyNames.end();
+ bool isOtherEnd = other.m_container == nullptr || other.m_it == other.m_container->m_keyNames.end();
+ return ((isThisEnd || isOtherEnd) ?
+ (isThisEnd == isOtherEnd) :
+ m_container->m_impl == other.m_container->m_impl && m_it == other.m_it);
}
bool
@@ -68,33 +80,30 @@
return !(*this == other);
}
-KeyContainer::KeyContainer()
-{
-}
-
-KeyContainer::KeyContainer(const Name& identity, std::set<Name>&& keyNames, shared_ptr<PibImpl> impl)
+KeyContainer::KeyContainer(const Name& identity, shared_ptr<PibImpl> impl)
: m_identity(identity)
- , m_keyNames(keyNames)
, m_impl(impl)
{
+ BOOST_ASSERT(impl != nullptr);
+ m_keyNames = impl->getKeysOfIdentity(identity);
}
KeyContainer::const_iterator
KeyContainer::begin() const
{
- return const_iterator(m_identity, m_keyNames.begin(), m_impl);
+ return const_iterator(m_keyNames.begin(), *this);
}
KeyContainer::const_iterator
KeyContainer::end() const
{
- return const_iterator(m_identity, m_keyNames.end(), m_impl);
+ return const_iterator();
}
KeyContainer::const_iterator
KeyContainer::find(const Name& keyName) const
{
- return const_iterator(m_identity, m_keyNames.find(keyName), m_impl);
+ return const_iterator(m_keyNames.find(keyName), *this);
}
size_t
@@ -103,6 +112,63 @@
return m_keyNames.size();
}
+Key
+KeyContainer::add(const uint8_t* key, size_t keyLen, const Name& keyName)
+{
+ if (m_identity != v2::extractIdentityFromKeyName(keyName)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Key name `" + keyName.toUri() + "` does not match identity "
+ "`" + m_identity.toUri() + "`"));
+ }
+
+ if (m_keyNames.count(keyName) == 0) {
+ m_keyNames.insert(keyName);
+ m_keys[keyName] = shared_ptr<detail::KeyImpl>(new detail::KeyImpl(keyName, key, keyLen, m_impl));
+ }
+
+ return get(keyName);
+}
+
+void
+KeyContainer::remove(const Name& keyName)
+{
+ if (m_identity != v2::extractIdentityFromKeyName(keyName)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Key name `" + keyName.toUri() + "` does not match identity "
+ "`" + m_identity.toUri() + "`"));
+ }
+
+ m_keyNames.erase(keyName);
+ m_keys.erase(keyName);
+ m_impl->removeKey(keyName);
+}
+
+Key
+KeyContainer::get(const Name& keyName) const
+{
+ if (m_identity != v2::extractIdentityFromKeyName(keyName)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Key name `" + keyName.toUri() + "` does not match identity "
+ "`" + m_identity.toUri() + "`"));
+ }
+
+ shared_ptr<detail::KeyImpl> key;
+ auto it = m_keys.find(keyName);
+
+ if (it != m_keys.end()) {
+ key = it->second;
+ }
+ else {
+ key = shared_ptr<detail::KeyImpl>(new detail::KeyImpl(keyName, m_impl));
+ m_keys[keyName] = key;
+ }
+
+ return Key(key);
+}
+
+bool
+KeyContainer::isConsistent() const
+{
+ return m_keyNames == m_impl->getKeysOfIdentity(m_identity);
+}
+
} // namespace pib
} // namespace security
} // namespace ndn
diff --git a/src/security/pib/key-container.hpp b/src/security/pib/key-container.hpp
index a593132..45d9127 100644
--- a/src/security/pib/key-container.hpp
+++ b/src/security/pib/key-container.hpp
@@ -23,6 +23,7 @@
#define NDN_SECURITY_PIB_KEY_CONTAINER_HPP
#include <set>
+#include <unordered_map>
#include "key.hpp"
namespace ndn {
@@ -31,13 +32,25 @@
class PibImpl;
-/// @brief A handler to search or enumerate keys of an identity.
-class KeyContainer
+namespace detail {
+class KeyImpl;
+class IdentityImpl;
+} // namespace detail
+
+/**
+ * @brief Container of keys of an identity
+ *
+ * The container is used to search/enumerate keys of an identity.
+ * The container can be created only by detail::IdentityImpl.
+ */
+class KeyContainer : noncopyable
{
public:
- class const_iterator
+ class const_iterator : public std::iterator<std::forward_iterator_tag, const Key>
{
public:
+ const_iterator();
+
Key
operator*();
@@ -54,12 +67,11 @@
operator!=(const const_iterator& other);
private:
- const_iterator(const Name& identity, std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+ const_iterator(std::set<Name>::const_iterator it, const KeyContainer& container);
private:
- Name m_identity;
std::set<Name>::const_iterator m_it;
- shared_ptr<PibImpl> m_impl;
+ const KeyContainer* m_container;
friend class KeyContainer;
};
@@ -67,10 +79,6 @@
typedef const_iterator iterator;
public:
- KeyContainer();
-
- KeyContainer(const Name& identity, std::set<Name>&& keyNames, shared_ptr<PibImpl> impl);
-
const_iterator
begin() const;
@@ -83,10 +91,63 @@
size_t
size() const;
+ /**
+ * @brief Add @p key of @p keyLen bytes with @p keyName into the container
+ * @throw std::invalid_argument @p keyName does not match the identity
+ */
+ Key
+ add(const uint8_t* key, size_t keyLen, const Name& keyName);
+
+ /**
+ * @brief Remove a key with @p keyName from the container
+ * @throw std::invalid_argument @p keyName does not match the identity
+ */
+ void
+ remove(const Name& keyName);
+
+ /**
+ * @brief Get a key with @p keyName from the container
+ * @throw std::invalid_argument @p keyName does not match the identity
+ * @throw Pib::Error the key does not exist
+ */
+ Key
+ get(const Name& keyName) const;
+
+ /**
+ * @brief Check if the container is consistent with the backend storage
+ *
+ * @note this method is heavyweight and should be used in debugging mode only.
+ */
+ bool
+ isConsistent() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Create key container for @p identity
+ * @param impl The PIB backend implementation.
+ */
+ KeyContainer(const Name& identity, shared_ptr<PibImpl> impl);
+
+ const std::set<Name>&
+ getKeyNames() const
+ {
+ return m_keyNames;
+ }
+
+ const std::unordered_map<Name, shared_ptr<detail::KeyImpl>>&
+ getLoadedKeys() const
+ {
+ return m_keys;
+ }
+
private:
Name m_identity;
std::set<Name> m_keyNames;
+ /// @brief Cache of loaded detail::KeyImpl.
+ mutable std::unordered_map<Name, shared_ptr<detail::KeyImpl>> m_keys;
+
shared_ptr<PibImpl> m_impl;
+ friend class detail::IdentityImpl;
};
} // namespace pib
diff --git a/src/security/pib/key.cpp b/src/security/pib/key.cpp
index 5890a9c..b4e6daf 100644
--- a/src/security/pib/key.cpp
+++ b/src/security/pib/key.cpp
@@ -20,161 +20,84 @@
*/
#include "key.hpp"
-#include "pib-impl.hpp"
-#include "pib.hpp"
+#include "detail/key-impl.hpp"
#include "../v2/certificate.hpp"
-#include "../transform/public-key.hpp"
namespace ndn {
namespace security {
namespace pib {
-Key::Key()
- : m_keyType(KeyType::NONE)
- , m_hasDefaultCertificate(false)
- , m_needRefreshCerts(false)
- , m_impl(nullptr)
+Key::Key() = default;
+
+Key::Key(weak_ptr<detail::KeyImpl> impl)
+ : m_impl(impl)
{
}
-Key::Key(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl)
- : m_keyName(keyName)
- , m_key(key, keyLen)
- , m_hasDefaultCertificate(false)
- , m_needRefreshCerts(true)
- , m_impl(impl)
-{
- validityCheck();
-
- m_identity = v2::extractIdentityFromKeyName(keyName);
- m_impl->addIdentity(m_identity);
- m_impl->addKey(m_identity, m_keyName, key, keyLen);
-
- transform::PublicKey publicKey;
- publicKey.loadPkcs8(key, keyLen);
- m_keyType = publicKey.getKeyType();
-}
-
-Key::Key(const Name& keyName, shared_ptr<PibImpl> impl)
- : m_keyName(keyName)
- , m_hasDefaultCertificate(false)
- , m_needRefreshCerts(true)
- , m_impl(impl)
-{
- validityCheck();
-
- m_identity = v2::extractIdentityFromKeyName(keyName);
- m_key = m_impl->getKeyBits(m_keyName);
-
- transform::PublicKey key;
- key.loadPkcs8(m_key.buf(), m_key.size());
- m_keyType = key.getKeyType();
-}
-
const Name&
Key::getName() const
{
- validityCheck();
-
- return m_keyName;
+ return lock()->getName();
}
const Name&
Key::getIdentity() const
{
- validityCheck();
+ return lock()->getIdentity();
+}
- return m_identity;
+KeyType
+Key::getKeyType() const
+{
+ return lock()->getKeyType();
}
const Buffer&
Key::getPublicKey() const
{
- validityCheck();
-
- return m_key;
+ return lock()->getPublicKey();
}
void
Key::addCertificate(const v2::Certificate& certificate)
{
- validityCheck();
-
- if (certificate.getKeyName() != m_keyName)
- BOOST_THROW_EXCEPTION(Pib::Error("Certificate name does not match key name"));
-
- if (!m_needRefreshCerts &&
- m_certificates.find(certificate.getName()) == m_certificates.end()) {
- // if we have already loaded all the certificate, but the new certificate is not one of them
- // the CertificateContainer should be refreshed
- m_needRefreshCerts = true;
- }
-
- m_impl->addCertificate(certificate);
+ return lock()->addCertificate(certificate);
}
void
Key::removeCertificate(const Name& certName)
{
- validityCheck();
-
- if (m_hasDefaultCertificate && m_defaultCertificate.getName() == certName)
- m_hasDefaultCertificate = false;
-
- m_impl->removeCertificate(certName);
- m_needRefreshCerts = true;
+ return lock()->removeCertificate(certName);
}
v2::Certificate
Key::getCertificate(const Name& certName) const
{
- validityCheck();
-
- return m_impl->getCertificate(certName);
+ return lock()->getCertificate(certName);
}
const CertificateContainer&
Key::getCertificates() const
{
- validityCheck();
-
- if (m_needRefreshCerts) {
- m_certificates = CertificateContainer(m_impl->getCertificatesOfKey(m_keyName), m_impl);
- m_needRefreshCerts = false;
- }
-
- return m_certificates;
+ return lock()->getCertificates();
}
const v2::Certificate&
Key::setDefaultCertificate(const Name& certName)
{
- validityCheck();
-
- m_impl->setDefaultCertificateOfKey(m_keyName, certName);
- m_defaultCertificate = m_impl->getCertificate(certName);
- m_hasDefaultCertificate = true;
- return m_defaultCertificate;
+ return lock()->setDefaultCertificate(certName);
}
const v2::Certificate&
Key::setDefaultCertificate(const v2::Certificate& certificate)
{
- addCertificate(certificate);
- return setDefaultCertificate(certificate.getName());
+ return lock()->setDefaultCertificate(certificate);
}
const v2::Certificate&
Key::getDefaultCertificate() const
{
- validityCheck();
-
- if (!m_hasDefaultCertificate) {
- m_defaultCertificate = m_impl->getDefaultCertificateOfKey(m_keyName);
- m_hasDefaultCertificate = true;
- }
-
- return m_defaultCertificate;
+ return lock()->getDefaultCertificate();
}
Key::operator bool() const
@@ -185,14 +108,19 @@
bool
Key::operator!() const
{
- return (m_impl == nullptr);
+ return m_impl.expired();
}
-void
-Key::validityCheck() const
+shared_ptr<detail::KeyImpl>
+Key::lock() const
{
- if (m_impl == nullptr)
- BOOST_THROW_EXCEPTION(std::domain_error("Invalid Key instance"));
+ auto impl = m_impl.lock();
+
+ if (impl == nullptr) {
+ BOOST_THROW_EXCEPTION(std::domain_error("Invalid key instance"));
+ }
+
+ return impl;
}
} // namespace pib
diff --git a/src/security/pib/key.hpp b/src/security/pib/key.hpp
index d99e427..69ceec8 100644
--- a/src/security/pib/key.hpp
+++ b/src/security/pib/key.hpp
@@ -22,7 +22,6 @@
#ifndef NDN_SECURITY_PIB_KEY_HPP
#define NDN_SECURITY_PIB_KEY_HPP
-#include "../../data.hpp"
#include "certificate-container.hpp"
#include "../security-common.hpp"
@@ -33,10 +32,12 @@
namespace pib {
-class PibImpl;
+namespace detail {
+class KeyImpl;
+} // namespace detail
/**
- * @brief represents a key
+ * @brief A frontend handle of a key instance
*
* Key is at the second level in PIB's Identity-Key-Certificate hierarchy. A Key has a Name
* (identity + "KEY" + keyId), and contains one or more certificates, one of which is set as
@@ -50,7 +51,7 @@
* @brief Default Constructor
*
* Key created using this default constructor is just a place holder.
- * It must obtain an actual instance from Identity::getKey(...). A typical
+ * It can obtain an actual instance from Identity::getKey(...). A typical
* usage would be for exception handling:
*
* Key key;
@@ -67,134 +68,114 @@
Key();
/**
- * @brief Create a Key with @p keyName
+ * @brief Create a Key with a backend implementation @p impl.
*
- * If the key/identity does not exist in the backend, create it in backend.
- *
- * @param keyName Key name
- * @param key The public key to add.
- * @param keyLen The length of the key.
- * @param impl The actual backend implementation.
+ * This method should only be used by KeyContainer.
*/
- Key(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl);
+ explicit
+ Key(weak_ptr<detail::KeyImpl> impl);
- /**
- * @brief Create a Key with @p keyName
- *
- * @param keyName Key name
- * @param impl The actual backend implementation.
- * @throws Pib::Error if the key does not exist.
+ /*
+ * @brief Get key name.
*/
- Key(const Name& keyName, shared_ptr<PibImpl> impl);
-
- /// @brief Get the key name.
const Name&
getName() const;
- /// @brief Get the name of the belonging identity.
+ /**
+ * @brief Get the name of the belonging identity.
+ */
const Name&
getIdentity() const;
- /// @brief Get key type.
+ /**
+ * @brief Get key type.
+ */
KeyType
- getKeyType() const
- {
- return m_keyType;
- }
+ getKeyType() const;
- /// @brief Get public key.
+ /**
+ * @brief Get public key bits.
+ */
const Buffer&
getPublicKey() const;
/**
- * @brief Get a certificate.
- *
- * @return the certificate
- * @throws Pib::Error if the certificate does not exist.
+ * @brief Get a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
*/
v2::Certificate
getCertificate(const Name& certName) const;
- /// @brief Get all certificates for this key.
+ /**
+ * @brief Get all certificates for this key.
+ */
const CertificateContainer&
getCertificates() const;
/**
* @brief Get the default certificate for this Key.
- *
- * @throws Pib::Error if the default certificate does not exist.
+ * @throw Pib::Error the default certificate does not exist.
*/
const v2::Certificate&
getDefaultCertificate() const;
- /// @brief Check if the Key instance is valid
+ /**
+ * @brief Check if the Key instance is valid.
+ */
operator bool() const;
- /// @brief Check if the Key instance is invalid
+ /**
+ * @brief Check if the Key instance is invalid.
+ */
bool
operator!() const;
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
/**
- * @brief Add a certificate.
- *
- * @param certificate The certificate to add.
+ * @brief Add @p certificate.
+ * @throw std::invalid_argument certificate name does not match key name
+ * @throw Pib::Error a certificate with the same name already exists
*/
void
addCertificate(const v2::Certificate& certificate);
/**
- * @brief Remove a certificate.
- *
- * @param certName The name of the certificate to delete.
+ * @brief Remove a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
*/
void
removeCertificate(const Name& certName);
/**
- * @brief Set the default certificate.
- *
- * @param certName The name of the default certificate of the key.
+ * @brief Set an existing certificate with @p certName as the default certificate
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
* @return the default certificate
- * @throws Pib::Error if the certificate does not exist.
*/
const v2::Certificate&
setDefaultCertificate(const Name& certName);
/**
- * @brief Set the default certificate.
- *
- * If the certificate does not exist, add it and set it as the default certificate of the key.
- * If the certificate exists, simply set it as the default certificate of the key.
- *
- * @param certificate The certificate to add.
+ * @brief Add @p certificate and set it as the default certificate of the key
+ * @throw std::invalid_argument @p certificate does not match key name
+ * @throw Pib::Error the certificate with the same name already exists.
* @return the default certificate
*/
const v2::Certificate&
setDefaultCertificate(const v2::Certificate& certificate);
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+private:
/**
- * @brief Check the validity of this instance
- *
- * @throws std::domain_error if the instance is invalid
+ * @brief Check the validity of the instance
+ * @return a shared_ptr when the instance is valid
+ * @throw std::domain_error the instance is invalid
*/
- void
- validityCheck() const;
+ shared_ptr<detail::KeyImpl>
+ lock() const;
private:
- Name m_identity;
- Name m_keyName;
- Buffer m_key;
- KeyType m_keyType;
-
- mutable bool m_hasDefaultCertificate;
- mutable v2::Certificate m_defaultCertificate;
-
- mutable bool m_needRefreshCerts;
- mutable CertificateContainer m_certificates;
-
- shared_ptr<PibImpl> m_impl;
+ weak_ptr<detail::KeyImpl> m_impl;
};
} // namespace pib
diff --git a/src/security/pib/pib-impl.hpp b/src/security/pib/pib-impl.hpp
index ef859a6..dc384a8 100644
--- a/src/security/pib/pib-impl.hpp
+++ b/src/security/pib/pib-impl.hpp
@@ -22,6 +22,7 @@
#ifndef NDN_SECURITY_PIB_PIB_IMPL_HPP
#define NDN_SECURITY_PIB_PIB_IMPL_HPP
+#include "pib.hpp"
#include <set>
#include "../v2/certificate.hpp"
@@ -131,7 +132,7 @@
* @brief Get the default identity.
*
* @return The name for the default identity.
- * @throws Pib::Error if no default identity.
+ * @throw Pib::Error no default identity.
*/
virtual Name
getDefaultIdentity() const = 0;
@@ -173,7 +174,7 @@
* @brief Get the key bits of a key with name @p keyName.
*
* @return key bits
- * @throws Pib::Error if the key does not exist.
+ * @throw Pib::Error the key does not exist.
*/
virtual Buffer
getKeyBits(const Name& keyName) const = 0;
@@ -192,7 +193,7 @@
/**
* @brief Set an key with @p keyName as the default key of an identity with name @p identity.
*
- * @throws Pib::Error if the key does not exist.
+ * @throw Pib::Error the key does not exist.
*/
virtual void
setDefaultKeyOfIdentity(const Name& identity, const Name& keyName) = 0;
@@ -200,7 +201,7 @@
/**
* @return The name of the default key of an identity with name @p identity.
*
- * @throws Pib::Error if no default key or the identity does not exist.
+ * @throw Pib::Error no default key or the identity does not exist.
*/
virtual Name
getDefaultKeyOfIdentity(const Name& identity) const = 0;
@@ -245,7 +246,7 @@
*
* @param certName The name of the certificate.
* @return the certificate.
- * @throws Pib::Error if the certificate does not exist.
+ * @throw Pib::Error the certificate does not exist.
*/
virtual v2::Certificate
getCertificate(const Name& certName) const = 0;
@@ -264,7 +265,7 @@
/**
* @brief Set a cert with name @p certName as the default of a key with @p keyName.
*
- * @throws Pib::Error if the certificate with name @p certName does not exist.
+ * @throw Pib::Error the certificate with name @p certName does not exist.
*/
virtual void
setDefaultCertificateOfKey(const Name& keyName, const Name& certName) = 0;
@@ -272,7 +273,7 @@
/**
* @return Get the default certificate of a key with @p keyName.
*
- * @throws Pib::Error if the default certificate does not exist.
+ * @throw Pib::Error the default certificate does not exist.
*/
virtual v2::Certificate
getDefaultCertificateOfKey(const Name& keyName) const = 0;
diff --git a/src/security/pib/pib-sqlite3.hpp b/src/security/pib/pib-sqlite3.hpp
index 8c47176..5571657 100644
--- a/src/security/pib/pib-sqlite3.hpp
+++ b/src/security/pib/pib-sqlite3.hpp
@@ -49,7 +49,7 @@
*
* @param dir The directory where the database file is located. By default, it points to the
* $HOME/.ndn directory.
- * @throws PibImpl::Error when initialization fails.
+ * @throw PibImpl::Error when initialization fails.
*/
explicit
PibSqlite3(const std::string& dir = "");
diff --git a/src/security/pib/pib.cpp b/src/security/pib/pib.cpp
index a29018e..6c5f316 100644
--- a/src/security/pib/pib.cpp
+++ b/src/security/pib/pib.cpp
@@ -29,10 +29,11 @@
Pib::Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl)
: m_scheme(scheme)
, m_location(location)
- , m_hasDefaultIdentity(false)
- , m_needRefreshIdentities(true)
+ , m_isDefaultIdentityLoaded(false)
+ , m_identities(impl)
, m_impl(impl)
{
+ BOOST_ASSERT(impl != nullptr);
}
Pib::~Pib() = default;
@@ -68,67 +69,69 @@
{
m_impl->clearIdentities();
m_impl->setTpmLocator("");
-
- m_hasDefaultIdentity = false;
- m_needRefreshIdentities = true;
+ m_isDefaultIdentityLoaded = false;
+ m_identities.reset();
}
Identity
Pib::addIdentity(const Name& identity)
{
- if (!m_needRefreshIdentities && m_identities.find(identity) == m_identities.end()) {
- // if we have already loaded all the identities, but the new identity is not one of them
- // the IdentityContainer should be refreshed
- m_needRefreshIdentities = true;
- }
- return Identity(identity, m_impl, true);
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ return m_identities.add(identity);
}
void
Pib::removeIdentity(const Name& identity)
{
- if (m_hasDefaultIdentity && m_defaultIdentity.getName() == identity)
- m_hasDefaultIdentity = false;
+ BOOST_ASSERT(m_identities.isConsistent());
- m_impl->removeIdentity(identity);
- m_needRefreshIdentities = true;
+ if (m_isDefaultIdentityLoaded && m_defaultIdentity.getName() == identity)
+ m_isDefaultIdentityLoaded = false;
+
+ m_identities.remove(identity);
}
Identity
Pib::getIdentity(const Name& identity) const
{
- return Identity(identity, m_impl, false);
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ return m_identities.get(identity);
}
const IdentityContainer&
Pib::getIdentities() const
{
- if (m_needRefreshIdentities) {
- m_identities = IdentityContainer(m_impl->getIdentities(), m_impl);
- m_needRefreshIdentities = false;
- }
+ BOOST_ASSERT(m_identities.isConsistent());
return m_identities;
}
-Identity&
+const Identity&
Pib::setDefaultIdentity(const Name& identityName)
{
- m_defaultIdentity = addIdentity(identityName);
- m_hasDefaultIdentity = true;
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ m_defaultIdentity = m_identities.add(identityName);
+ m_isDefaultIdentityLoaded = true;
m_impl->setDefaultIdentity(identityName);
return m_defaultIdentity;
}
-Identity&
+const Identity&
Pib::getDefaultIdentity() const
{
- if (!m_hasDefaultIdentity) {
- m_defaultIdentity = Identity(m_impl->getDefaultIdentity(), m_impl, false);
- m_hasDefaultIdentity = true;
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ if (!m_isDefaultIdentityLoaded) {
+ m_defaultIdentity = m_identities.get(m_impl->getDefaultIdentity());
+ m_isDefaultIdentityLoaded = true;
}
+ BOOST_ASSERT(m_impl->getDefaultIdentity() == m_defaultIdentity.getName());
+
return m_defaultIdentity;
}
diff --git a/src/security/pib/pib.hpp b/src/security/pib/pib.hpp
index 06f100d..47dbd5c 100644
--- a/src/security/pib/pib.hpp
+++ b/src/security/pib/pib.hpp
@@ -51,9 +51,6 @@
class Pib : noncopyable
{
public:
- friend class KeyChain;
-
-public:
/// @brief represents a semantic error
class Error : public std::runtime_error
{
@@ -107,8 +104,6 @@
/**
* @brief Get an identity with name @p identityName.
- *
- * @param identityName The name for the identity to get.
* @throw Pib::Error if the identity does not exist.
*/
Identity
@@ -120,15 +115,22 @@
/**
* @brief Get the default identity.
- *
- * @return the default identity.
- * @throws Pib::Error if no default identity.
+ * @throw Pib::Error if no default identity.
*/
- Identity&
+ const Identity&
getDefaultIdentity() const;
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
/*
+ * @brief Create a Pib instance
+ *
+ * @param scheme The scheme for the Pib
+ * @param location The location for the Pib
+ * @param impl The backend implementation
+ */
+ Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl);
+
+ /*
* @brief Create an identity with name @p identityName and return a reference to it.
*
* If there already exists an identity for the name @p identityName, then it is returned.
@@ -136,39 +138,34 @@
*
* @param identityName The name for the identity to be added
*/
- Identity
- addIdentity(const Name& identityName);
-
- /*
- * @brief Remove an identity with name @p identityName.
- *
- * If the default identity is being removed, no default identity will be selected.
- *
- * @param identityName The name for the identity to be deleted
- */
- void
- removeIdentity(const Name& identityName);
/**
- * @brief Set an identity with name @p identityName as the default identity.
+ * @brief Add an @p identity.
*
- * Also create the identity if it does not exist.
+ * If no default identity is set before, the new identity will be set as the default identity
*
- * @param identityName The name for the default identity.
- * @return the default identity
+ * @return handle of the added identity.
*/
- Identity&
- setDefaultIdentity(const Name& identityName);
+ Identity
+ addIdentity(const Name& identity);
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/*
- * @brief Create a new Pib with the specified @p location
+ * @brief Remove an @p identity.
*
- * @param scheme The scheme for the Pib
- * @param location The location for the Pib
- * @param impl The backend implementation
+ * If the default identity is being removed, no default identity will be selected.
*/
- Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl);
+ void
+ removeIdentity(const Name& identity);
+
+ /**
+ * @brief Set an @p identity as the default identity.
+ *
+ * Create the identity if it does not exist.
+ *
+ * @return handle of the default identity
+ */
+ const Identity&
+ setDefaultIdentity(const Name& identity);
shared_ptr<PibImpl>
getImpl()
@@ -180,13 +177,14 @@
std::string m_scheme;
std::string m_location;
- mutable bool m_hasDefaultIdentity;
+ mutable bool m_isDefaultIdentityLoaded;
mutable Identity m_defaultIdentity;
- mutable bool m_needRefreshIdentities;
- mutable IdentityContainer m_identities;
+ IdentityContainer m_identities;
shared_ptr<PibImpl> m_impl;
+
+ friend class KeyChain;
};
} // namespace pib
diff --git a/src/util/concepts.hpp b/src/util/concepts.hpp
index 8d4567e..a8c7fdd 100644
--- a/src/util/concepts.hpp
+++ b/src/util/concepts.hpp
@@ -1,6 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2014-2017, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -96,6 +102,41 @@
}
};
+// NDN_CXX_ASSERT_DEFAULT_CONSTRUCTIBLE and NDN_CXX_ASSERT_FORWARD_ITERATOR
+// originally written as part of NFD codebase
+
+namespace detail {
+
+// As of Boost 1.54.0, the internal implementation of BOOST_CONCEPT_ASSERT does not allow
+// multiple assertions on the same line, so we have to combine multiple concepts together.
+
+template<typename T>
+class StlForwardIteratorConcept : public boost::ForwardIterator<T>
+ , public boost::DefaultConstructible<T>
+{
+};
+
+} // namespace detail
+
+/** \brief assert T is default constructible
+ * \sa http://en.cppreference.com/w/cpp/concept/DefaultConstructible
+ */
+#define NDN_CXX_ASSERT_DEFAULT_CONSTRUCTIBLE(T) \
+ static_assert(std::is_default_constructible<T>::value, \
+ #T " must be default-constructible"); \
+ BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<T>))
+
+/** \brief assert T is a forward iterator
+ * \sa http://en.cppreference.com/w/cpp/concept/ForwardIterator
+ * \note A forward iterator should be default constructible, but boost::ForwardIterator follows
+ * SGI standard which doesn't require DefaultConstructible, so a separate check is needed.
+ */
+#define NDN_CXX_ASSERT_FORWARD_ITERATOR(T) \
+ BOOST_CONCEPT_ASSERT((::ndn::detail::StlForwardIteratorConcept<T>)); \
+ static_assert(std::is_default_constructible<T>::value, \
+ #T " must be default-constructible")
+
+
} // namespace ndn
#endif // NDN_UTIL_CONCEPTS_HPP
diff --git a/tests/unit-tests/security/pib/certificate-container.t.cpp b/tests/unit-tests/security/pib/certificate-container.t.cpp
index 5edbfb2..4eeaa4a 100644
--- a/tests/unit-tests/security/pib/certificate-container.t.cpp
+++ b/tests/unit-tests/security/pib/certificate-container.t.cpp
@@ -35,25 +35,100 @@
BOOST_AUTO_TEST_SUITE(Security)
BOOST_AUTO_TEST_SUITE(Pib)
-BOOST_AUTO_TEST_SUITE(TestCertificateContainer)
+BOOST_FIXTURE_TEST_SUITE(TestCertificateContainer, PibDataFixture)
using pib::Pib;
-BOOST_FIXTURE_TEST_CASE(TestCertificateContainer, PibDataFixture)
+BOOST_AUTO_TEST_CASE(Basic)
{
auto pibImpl = make_shared<PibMemory>();
- Pib pib("pib-memory", "", pibImpl);
- Identity identity1 = pib.addIdentity(id1);
- Key key11 = identity1.addKey(id1Key1.buf(), id1Key1.size(), id1Key1Name);
- key11.addCertificate(id1Key1Cert1);
- key11.addCertificate(id1Key1Cert2);
+ // start with an empty container
+ CertificateContainer container(id1Key1Name, pibImpl);
+ BOOST_CHECK_EQUAL(container.size(), 0);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 0);
- CertificateContainer container = key11.getCertificates();
+ // add one cert
+ container.add(id1Key1Cert1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Cert1.getName()) != container.end());
+
+ // add the same cert again
+ container.add(id1Key1Cert1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Cert1.getName()) != container.end());
+
+ // add another cert
+ container.add(id1Key1Cert2);
BOOST_CHECK_EQUAL(container.size(), 2);
+ BOOST_CHECK_EQUAL(container.getCache().size(), 2);
BOOST_CHECK(container.find(id1Key1Cert1.getName()) != container.end());
BOOST_CHECK(container.find(id1Key1Cert2.getName()) != container.end());
+ // get certs
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key1Cert1.getName()));
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key1Cert2.getName()));
+ Name id1Key1Cert3Name = id1Key1Name;
+ id1Key1Cert3Name.append("issuer").appendVersion(3);
+ BOOST_CHECK_THROW(container.get(id1Key1Cert3Name), Pib::Error);
+
+ // check cert
+ v2::Certificate cert1 = container.get(id1Key1Cert1.getName());
+ v2::Certificate cert2 = container.get(id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(cert1, id1Key1Cert1);
+ BOOST_CHECK_EQUAL(cert2, id1Key1Cert2);
+
+ // create another container from the same PibImpl
+ // cache should be empty
+ CertificateContainer container2(id1Key1Name, pibImpl);
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 0);
+
+ // get certificate, cache should be filled
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key1Cert1.getName()));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 1);
+
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key1Cert2.getName()));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 2);
+
+ // remove a certificate
+ container2.remove(id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(container2.size(), 1);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 1);
+ BOOST_CHECK(container2.find(id1Key1Cert1.getName()) == container2.end());
+ BOOST_CHECK(container2.find(id1Key1Cert2.getName()) != container2.end());
+
+ // remove another certificate
+ container2.remove(id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(container2.size(), 0);
+ BOOST_CHECK_EQUAL(container2.getCache().size(), 0);
+ BOOST_CHECK(container2.find(id1Key1Cert2.getName()) == container2.end());
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ CertificateContainer container(id1Key1Name, pibImpl);
+
+ BOOST_CHECK_THROW(container.add(id1Key2Cert1), std::invalid_argument);
+ BOOST_CHECK_THROW(container.remove(id1Key2Cert1.getName()), std::invalid_argument);
+ BOOST_CHECK_THROW(container.get(id1Key2Cert1.getName()), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(Iterator)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ // start with an empty container
+ CertificateContainer container(id1Key1Name, pibImpl);
+ container.add(id1Key1Cert1);
+ container.add(id1Key1Cert2);
+
std::set<Name> certNames;
certNames.insert(id1Key1Cert1.getName());
certNames.insert(id1Key1Cert2.getName());
@@ -76,6 +151,10 @@
count++;
}
BOOST_CHECK_EQUAL(count, 2);
+
+ BOOST_CHECK(CertificateContainer::const_iterator() == CertificateContainer::const_iterator());
+ BOOST_CHECK(CertificateContainer::const_iterator() == container.end());
+ BOOST_CHECK(container.end() == CertificateContainer::const_iterator());
}
BOOST_AUTO_TEST_SUITE_END() // TestCertificateContainer
diff --git a/tests/unit-tests/security/pib/detail/identity-impl.t.cpp b/tests/unit-tests/security/pib/detail/identity-impl.t.cpp
new file mode 100644
index 0000000..10c7bb8
--- /dev/null
+++ b/tests/unit-tests/security/pib/detail/identity-impl.t.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/detail/identity-impl.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+#include "../pib-data-fixture.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_AUTO_TEST_SUITE(Detail)
+BOOST_FIXTURE_TEST_SUITE(TestIdentityImpl, ndn::security::tests::PibDataFixture)
+
+using security::Pib;
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ IdentityImpl identity1(id1, pibImpl, true);
+
+ BOOST_CHECK_EQUAL(identity1.getName(), id1);
+}
+
+BOOST_AUTO_TEST_CASE(KeyOperation)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ IdentityImpl identity1(id1, pibImpl, true);
+ BOOST_CHECK_NO_THROW(IdentityImpl(id1, pibImpl, false));
+
+ // identity does not have any key
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 0);
+
+ // get non-existing key, throw Pib::Error
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ // get default key, throw Pib::Error
+ BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
+ // set non-existing key as default key, throw Pib::Error
+ BOOST_REQUIRE_THROW(identity1.setDefaultKey(id1Key1Name), Pib::Error);
+
+ // add key
+ identity1.addKey(id1Key1.buf(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_NO_THROW(identity1.getKey(id1Key1Name));
+
+ // new key becomes default key when there is no default key
+ BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
+ const Key& defaultKey0 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey0.getName(), id1Key1Name);
+ BOOST_CHECK(defaultKey0.getPublicKey() == id1Key1);
+
+ // remove key
+ identity1.removeKey(id1Key1Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
+
+ // set default key directly
+ BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1.buf(), id1Key1.size(), id1Key1Name));
+ BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
+ BOOST_CHECK_NO_THROW(identity1.getKey(id1Key1Name));
+
+ // check default key
+ const Key& defaultKey1 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey1.getName(), id1Key1Name);
+ BOOST_CHECK(defaultKey1.getPublicKey() == id1Key1);
+
+ // add another key
+ identity1.addKey(id1Key2.buf(), id1Key2.size(), id1Key2Name);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 2);
+
+ // set default key through name
+ BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key2Name));
+ BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
+ const Key& defaultKey2 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey2.getName(), id1Key2Name);
+ BOOST_CHECK(defaultKey2.getPublicKey() == id1Key2);
+
+ // remove key
+ identity1.removeKey(id1Key1Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 1);
+
+ // set default key directly again, change the default setting
+ BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1.buf(), id1Key1.size(), id1Key1Name));
+ const Key& defaultKey3 = identity1.getDefaultKey();
+ BOOST_CHECK_EQUAL(defaultKey3.getName(), id1Key1Name);
+ BOOST_CHECK(defaultKey3.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 2);
+
+ // remove all keys
+ identity1.removeKey(id1Key1Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 1);
+ identity1.removeKey(id1Key2Name);
+ BOOST_CHECK_THROW(identity1.getKey(id1Key2Name), Pib::Error);
+ BOOST_CHECK_EQUAL(identity1.getKeys().size(), 0);
+ BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+
+ BOOST_CHECK_THROW(IdentityImpl(id1, pibImpl, false), Pib::Error);
+ IdentityImpl identity1(id1, pibImpl, true);
+
+ identity1.addKey(id1Key1.buf(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_THROW(identity1.addKey(id1Key1.buf(), id1Key1.size(), id1Key1Name), Pib::Error);
+ BOOST_CHECK_THROW(identity1.addKey(id2Key1.buf(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.removeKey(id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.getKey(id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.setDefaultKey(id2Key1.buf(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(identity1.setDefaultKey(id2Key1Name), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestIdentityImpl
+BOOST_AUTO_TEST_SUITE_END() // Detail
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/pib/detail/key-impl.t.cpp b/tests/unit-tests/security/pib/detail/key-impl.t.cpp
new file mode 100644
index 0000000..b25a870
--- /dev/null
+++ b/tests/unit-tests/security/pib/detail/key-impl.t.cpp
@@ -0,0 +1,164 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/pib/detail/key-impl.hpp"
+#include "security/pib/pib.hpp"
+#include "security/pib/pib-memory.hpp"
+#include "../pib-data-fixture.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Pib)
+BOOST_AUTO_TEST_SUITE(Detail)
+BOOST_FIXTURE_TEST_SUITE(TestKeyImpl, ndn::security::tests::PibDataFixture)
+
+using security::Pib;
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ KeyImpl key11(id1Key1Name, id1Key1.buf(), id1Key1.size(), pibImpl);
+
+ BOOST_CHECK_EQUAL(key11.getName(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key11.getIdentity(), id1);
+ BOOST_CHECK_EQUAL(key11.getKeyType(), KeyType::EC);
+ BOOST_CHECK(key11.getPublicKey() == id1Key1);
+
+ KeyImpl key11Bak(id1Key1Name, pibImpl);
+ BOOST_CHECK_EQUAL(key11Bak.getName(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key11Bak.getIdentity(), id1);
+ BOOST_CHECK_EQUAL(key11Bak.getKeyType(), KeyType::EC);
+ BOOST_CHECK(key11Bak.getPublicKey() == id1Key1);
+}
+
+BOOST_AUTO_TEST_CASE(CertificateOperation)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+ KeyImpl key11(id1Key1Name, id1Key1.buf(), id1Key1.size(), pibImpl);
+ BOOST_CHECK_NO_THROW(KeyImpl(id1Key1Name, pibImpl));
+
+ // key does not have any certificate
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 0);
+
+ // get non-existing certificate, throw Pib::Error
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ // get default certificate, throw Pib::Error
+ BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
+ // set non-existing certificate as default certificate, throw Pib::Error
+ BOOST_REQUIRE_THROW(key11.setDefaultCertificate(id1Key1Cert1.getName()), Pib::Error);
+
+ // add certificate
+ key11.addCertificate(id1Key1Cert1);
+ BOOST_CHECK_NO_THROW(key11.getCertificate(id1Key1Cert1.getName()));
+
+ // new certificate becomes default certificate when there was no default certificate
+ BOOST_REQUIRE_NO_THROW(key11.getDefaultCertificate());
+ const auto& defaultCert0 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert0.getName(), id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(defaultCert0, id1Key1Cert1);
+
+ // remove certificate
+ key11.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
+
+ // set default certificate directly
+ BOOST_REQUIRE_NO_THROW(key11.setDefaultCertificate(id1Key1Cert1));
+ BOOST_REQUIRE_NO_THROW(key11.getDefaultCertificate());
+ BOOST_CHECK_NO_THROW(key11.getCertificate(id1Key1Cert1.getName()));
+
+ // check default cert
+ const auto& defaultCert1 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert1.getName(), id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(defaultCert1, id1Key1Cert1);
+
+ // add another certificate
+ key11.addCertificate(id1Key1Cert2);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 2);
+
+ // set default certificate through name
+ BOOST_REQUIRE_NO_THROW(key11.setDefaultCertificate(id1Key1Cert2.getName()));
+ BOOST_REQUIRE_NO_THROW(key11.getDefaultCertificate());
+ const auto& defaultCert2 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert2.getName(), id1Key1Cert2.getName());
+ BOOST_CHECK_EQUAL(defaultCert2, id1Key1Cert2);
+
+ // remove certificate
+ key11.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 1);
+
+ // set default certificate directly again, change the default setting
+ BOOST_REQUIRE_NO_THROW(key11.setDefaultCertificate(id1Key1Cert1));
+ const auto& defaultCert3 = key11.getDefaultCertificate();
+ BOOST_CHECK_EQUAL(defaultCert3.getName(), id1Key1Cert1.getName());
+ BOOST_CHECK_EQUAL(defaultCert3, id1Key1Cert1);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 2);
+
+ // remove all certificates
+ key11.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 1);
+ key11.removeCertificate(id1Key1Cert2.getName());
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert2.getName()), Pib::Error);
+ BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
+ BOOST_CHECK_EQUAL(key11.getCertificates().size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<pib::PibMemory>();
+
+ BOOST_CHECK_THROW(KeyImpl(id1Key1Name, pibImpl), Pib::Error);
+ KeyImpl key11(id1Key1Name, id1Key1.buf(), id1Key1.size(), pibImpl);
+ BOOST_CHECK_THROW(KeyImpl(id1Key1Name, id1Key1.buf(), id1Key1.size(), pibImpl), Pib::Error);
+
+ BOOST_CHECK_THROW(KeyImpl(Name("/wrong"), pibImpl), std::invalid_argument);
+ BOOST_CHECK_THROW(KeyImpl(Name("/wrong"), id1Key1.buf(), id1Key1.size(), pibImpl), std::invalid_argument);
+ Buffer wrongKey;
+ BOOST_CHECK_THROW(KeyImpl(id1Key2Name, wrongKey.buf(), wrongKey.size(), pibImpl), std::invalid_argument);
+
+ key11.addCertificate(id1Key1Cert1);
+ BOOST_CHECK_THROW(key11.addCertificate(id1Key1Cert1), Pib::Error);
+ BOOST_CHECK_THROW(key11.addCertificate(id1Key2Cert1), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.removeCertificate(id1Key2Cert1.getName()), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.getCertificate(id1Key2Cert1.getName()), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.setDefaultCertificate(id1Key2Cert1), std::invalid_argument);
+ BOOST_CHECK_THROW(key11.setDefaultCertificate(id1Key2Cert1.getName()), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestKeyImpl
+BOOST_AUTO_TEST_SUITE_END() // Detail
+BOOST_AUTO_TEST_SUITE_END() // Pib
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/pib/identity-container.t.cpp b/tests/unit-tests/security/pib/identity-container.t.cpp
index b9af408..92420db 100644
--- a/tests/unit-tests/security/pib/identity-container.t.cpp
+++ b/tests/unit-tests/security/pib/identity-container.t.cpp
@@ -35,23 +35,89 @@
BOOST_AUTO_TEST_SUITE(Security)
BOOST_AUTO_TEST_SUITE(Pib)
-BOOST_AUTO_TEST_SUITE(TestIdentityContainer)
+BOOST_FIXTURE_TEST_SUITE(TestIdentityContainer, PibDataFixture)
using pib::Pib;
-BOOST_FIXTURE_TEST_CASE(Basic, PibDataFixture)
+BOOST_AUTO_TEST_CASE(Basic)
{
auto pibImpl = make_shared<PibMemory>();
- Pib pib("pib-memory", "", pibImpl);
- Identity identity1 = pib.addIdentity(id1);
- Identity identity2 = pib.addIdentity(id2);
+ // start with an empty container
+ IdentityContainer container(pibImpl);
+ BOOST_CHECK_EQUAL(container.size(), 0);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 0);
- IdentityContainer container = pib.getIdentities();
+ // add the first identity
+ Identity identity11 = container.add(id1);
+ BOOST_CHECK_EQUAL(identity11.getName(), id1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 1);
+ BOOST_CHECK(container.find(id1) != container.end());
+
+ // add the same identity again
+ Identity identity12 = container.add(id1);
+ BOOST_CHECK_EQUAL(identity12.getName(), id1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 1);
+ BOOST_CHECK(container.find(id1) != container.end());
+
+ // add the second identity
+ Identity identity21 = container.add(id2);
+ BOOST_CHECK_EQUAL(identity21.getName(), id2);
BOOST_CHECK_EQUAL(container.size(), 2);
+ BOOST_CHECK_EQUAL(container.getLoadedIdentities().size(), 2);
BOOST_CHECK(container.find(id1) != container.end());
BOOST_CHECK(container.find(id2) != container.end());
+ // get identities
+ BOOST_REQUIRE_NO_THROW(container.get(id1));
+ BOOST_REQUIRE_NO_THROW(container.get(id2));
+ BOOST_CHECK_THROW(container.get(Name("/non-existing")), Pib::Error);
+
+ // check identity
+ Identity identity1 = container.get(id1);
+ Identity identity2 = container.get(id2);
+ BOOST_CHECK_EQUAL(identity1.getName(), id1);
+ BOOST_CHECK_EQUAL(identity2.getName(), id2);
+
+ // create another container from the same PibImpl
+ // cache should be empty
+ IdentityContainer container2(pibImpl);
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 0);
+
+ // get key, cache should be filled
+ BOOST_REQUIRE_NO_THROW(container2.get(id1));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 1);
+
+ BOOST_REQUIRE_NO_THROW(container2.get(id2));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 2);
+
+ // remove a key
+ container2.remove(id1);
+ BOOST_CHECK_EQUAL(container2.size(), 1);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 1);
+ BOOST_CHECK(container2.find(id1) == container2.end());
+ BOOST_CHECK(container2.find(id2) != container2.end());
+
+ // remove another key
+ container2.remove(id2);
+ BOOST_CHECK_EQUAL(container2.size(), 0);
+ BOOST_CHECK_EQUAL(container2.getLoadedIdentities().size(), 0);
+ BOOST_CHECK(container2.find(id2) == container2.end());
+
+}
+
+BOOST_AUTO_TEST_CASE(Iterator)
+{
+ auto pibImpl = make_shared<PibMemory>();
+ IdentityContainer container(pibImpl);
+ container.add(id1);
+ container.add(id2);
+
std::set<Name> idNames;
idNames.insert(id1);
idNames.insert(id2);
@@ -74,6 +140,10 @@
count++;
}
BOOST_CHECK_EQUAL(count, 2);
+
+ BOOST_CHECK(IdentityContainer::const_iterator() == IdentityContainer::const_iterator());
+ BOOST_CHECK(IdentityContainer::const_iterator() == container.end());
+ BOOST_CHECK(container.end() == IdentityContainer::const_iterator());
}
BOOST_AUTO_TEST_SUITE_END() // TestIdentityContainer
diff --git a/tests/unit-tests/security/pib/identity.t.cpp b/tests/unit-tests/security/pib/identity.t.cpp
index 3704d92..49bd8da 100644
--- a/tests/unit-tests/security/pib/identity.t.cpp
+++ b/tests/unit-tests/security/pib/identity.t.cpp
@@ -22,6 +22,7 @@
#include "security/pib/identity.hpp"
#include "security/pib/pib.hpp"
#include "security/pib/pib-memory.hpp"
+#include "security/pib/detail/identity-impl.hpp"
#include "boost-test.hpp"
#include "pib-data-fixture.hpp"
@@ -41,7 +42,8 @@
BOOST_AUTO_TEST_CASE(ValidityChecking)
{
- // identity
+ using security::pib::detail::IdentityImpl;
+
Identity id;
BOOST_CHECK_EQUAL(static_cast<bool>(id), false);
@@ -52,7 +54,8 @@
else
BOOST_CHECK(true);
- id = Identity(id1, make_shared<PibMemory>(), true);
+ auto identityImpl = make_shared<IdentityImpl>(id1, make_shared<PibMemory>(), true);
+ id = Identity(identityImpl);
BOOST_CHECK_EQUAL(static_cast<bool>(id), true);
BOOST_CHECK_EQUAL(!id, false);
@@ -63,41 +66,26 @@
BOOST_CHECK(false);
}
-BOOST_AUTO_TEST_CASE(KeyOperations)
+/**
+ * pib::Identity is a wrapper of pib::detail::IdentityImpl. Since the functionalities of
+ * IdentityImpl have already been tested in detail/identity-impl.t.cpp, we only test the shared
+ * property of pib::Identity in this test case.
+ */
+BOOST_AUTO_TEST_CASE(Share)
{
- Identity identity1(id1, make_shared<PibMemory>(), true);
+ using security::pib::detail::IdentityImpl;
- // Key does not exist, throw Error
+ auto identityImpl = make_shared<IdentityImpl>(id1, make_shared<pib::PibMemory>(), true);
+ Identity identity1(identityImpl);
+ Identity identity2(identityImpl);
+
+ identity1.addKey(id1Key1.buf(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_NO_THROW(identity2.getKey(id1Key1Name));
+ identity2.removeKey(id1Key1Name);
BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
- // Key name does not match identity name, throw Error
- BOOST_CHECK_THROW(identity1.getKey(id2Key1Name), Pib::Error);
- // Add key
- Key key11 = identity1.addKey(id1Key1.buf(), id1Key1.size(), id1Key1Name);
- BOOST_CHECK_NO_THROW(identity1.getKey(id1Key1Name));
- // Key name does not match identity name, throw Error
- BOOST_CHECK_THROW(identity1.addKey(id2Key1.buf(), id2Key1.size(), id2Key1Name), Pib::Error);
-
- // Remove key
- identity1.removeKey(id1Key1Name);
- BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
- // Key name does not match identity name, throw Error
- BOOST_CHECK_THROW(identity1.removeKey(id2Key1Name), Pib::Error);
-
- // Default key does not exist, throw Error
- BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
-
- // Set default key but the key does not exist, throw Error
- BOOST_CHECK_THROW(identity1.setDefaultKey(id1Key1Name), Pib::Error);
- // Set default key
- BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1.buf(), id1Key1.size(), id1Key1Name));
- BOOST_CHECK_NO_THROW(identity1.getDefaultKey());
- BOOST_CHECK_EQUAL(identity1.getDefaultKey().getName(), id1Key1Name);
-
- // Remove the default key
- identity1.removeKey(id1Key1Name);
- BOOST_CHECK_THROW(identity1.getKey(id1Key1Name), Pib::Error);
- BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
+ identity1.setDefaultKey(id1Key1.buf(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_NO_THROW(identity2.getDefaultKey());
}
BOOST_AUTO_TEST_SUITE_END() // TestIdentity
diff --git a/tests/unit-tests/security/pib/key-container.t.cpp b/tests/unit-tests/security/pib/key-container.t.cpp
index 812fab4..5b7961e 100644
--- a/tests/unit-tests/security/pib/key-container.t.cpp
+++ b/tests/unit-tests/security/pib/key-container.t.cpp
@@ -35,25 +35,106 @@
BOOST_AUTO_TEST_SUITE(Security)
BOOST_AUTO_TEST_SUITE(Pib)
-BOOST_AUTO_TEST_SUITE(TestKeyContainer)
+BOOST_FIXTURE_TEST_SUITE(TestKeyContainer, PibDataFixture)
using pib::Pib;
-BOOST_FIXTURE_TEST_CASE(Basic, PibDataFixture)
+BOOST_AUTO_TEST_CASE(Basic)
{
auto pibImpl = make_shared<PibMemory>();
- Pib pib("pib-memory", "", pibImpl);
- Identity identity1 = pib.addIdentity(id1);
+ // start with an empty container
+ KeyContainer container(id1, pibImpl);
+ BOOST_CHECK_EQUAL(container.size(), 0);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 0);
- Key key11 = identity1.addKey(id1Key1.buf(), id1Key1.size(), id1Key1Name);
- Key key12 = identity1.addKey(id1Key2.buf(), id1Key2.size(), id1Key2Name);
+ // add the first key
+ Key key11 = container.add(id1Key1.buf(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key11.getName(), id1Key1Name);
+ BOOST_CHECK(key11.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Name) != container.end());
- KeyContainer container = identity1.getKeys();
+ // add the same key again
+ Key key12 = container.add(id1Key1.buf(), id1Key1.size(), id1Key1Name);
+ BOOST_CHECK_EQUAL(key12.getName(), id1Key1Name);
+ BOOST_CHECK(key12.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(container.size(), 1);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 1);
+ BOOST_CHECK(container.find(id1Key1Name) != container.end());
+
+ // add the second key
+ Key key21 = container.add(id1Key2.buf(), id1Key2.size(), id1Key2Name);
+ BOOST_CHECK_EQUAL(key21.getName(), id1Key2Name);
+ BOOST_CHECK(key21.getPublicKey() == id1Key2);
BOOST_CHECK_EQUAL(container.size(), 2);
+ BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 2);
BOOST_CHECK(container.find(id1Key1Name) != container.end());
BOOST_CHECK(container.find(id1Key2Name) != container.end());
+ // get keys
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key1Name));
+ BOOST_REQUIRE_NO_THROW(container.get(id1Key2Name));
+ Name id1Key3Name = v2::constructKeyName(id1, name::Component("non-existing-id"));
+ BOOST_CHECK_THROW(container.get(id1Key3Name), Pib::Error);
+
+ // check key
+ Key key1 = container.get(id1Key1Name);
+ Key key2 = container.get(id1Key2Name);
+ BOOST_CHECK_EQUAL(key1.getName(), id1Key1Name);
+ BOOST_CHECK(key1.getPublicKey() == id1Key1);
+ BOOST_CHECK_EQUAL(key2.getName(), id1Key2Name);
+ BOOST_CHECK(key2.getPublicKey() == id1Key2);
+
+ // create another container from the same PibImpl
+ // cache should be empty
+ KeyContainer container2(id1, pibImpl);
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 0);
+
+ // get key, cache should be filled
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key1Name));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 1);
+
+ BOOST_REQUIRE_NO_THROW(container2.get(id1Key2Name));
+ BOOST_CHECK_EQUAL(container2.size(), 2);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 2);
+
+ // remove a key
+ container2.remove(id1Key1Name);
+ BOOST_CHECK_EQUAL(container2.size(), 1);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 1);
+ BOOST_CHECK(container2.find(id1Key1Name) == container2.end());
+ BOOST_CHECK(container2.find(id1Key2Name) != container2.end());
+
+ // remove another key
+ container2.remove(id1Key2Name);
+ BOOST_CHECK_EQUAL(container2.size(), 0);
+ BOOST_CHECK_EQUAL(container2.getLoadedKeys().size(), 0);
+ BOOST_CHECK(container2.find(id1Key2Name) == container2.end());
+}
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ auto pibImpl = make_shared<PibMemory>();
+
+ KeyContainer container(id1, pibImpl);
+
+ BOOST_CHECK_THROW(container.add(id2Key1.buf(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(container.remove(id2Key1Name), std::invalid_argument);
+ BOOST_CHECK_THROW(container.get(id2Key1Name), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(Iterator)
+{
+ auto pibImpl = make_shared<PibMemory>();
+ KeyContainer container(id1, pibImpl);
+
+ container.add(id1Key1.buf(), id1Key1.size(), id1Key1Name);
+ container.add(id1Key2.buf(), id1Key2.size(), id1Key2Name);
+
std::set<Name> keyNames;
keyNames.insert(id1Key1Name);
keyNames.insert(id1Key2Name);
@@ -77,6 +158,10 @@
count++;
}
BOOST_CHECK_EQUAL(count, 2);
+
+ BOOST_CHECK(KeyContainer::const_iterator() == KeyContainer::const_iterator());
+ BOOST_CHECK(KeyContainer::const_iterator() == container.end());
+ BOOST_CHECK(container.end() == KeyContainer::const_iterator());
}
BOOST_AUTO_TEST_SUITE_END() // TestKeyContainer
diff --git a/tests/unit-tests/security/pib/key.t.cpp b/tests/unit-tests/security/pib/key.t.cpp
index 9391f53..afa65e7 100644
--- a/tests/unit-tests/security/pib/key.t.cpp
+++ b/tests/unit-tests/security/pib/key.t.cpp
@@ -22,6 +22,7 @@
#include "security/pib/key.hpp"
#include "security/pib/pib.hpp"
#include "security/pib/pib-memory.hpp"
+#include "security/pib/detail/key-impl.hpp"
#include "boost-test.hpp"
#include "pib-data-fixture.hpp"
@@ -41,6 +42,8 @@
BOOST_AUTO_TEST_CASE(ValidityChecking)
{
+ using security::pib::detail::KeyImpl;
+
Key key;
BOOST_CHECK_EQUAL(static_cast<bool>(key), false);
@@ -51,7 +54,8 @@
else
BOOST_CHECK(true);
- key = Key(id1Key1Name, id1Key1.buf(), id1Key1.size(), make_shared<PibMemory>());
+ auto keyImpl = make_shared<KeyImpl>(id1Key1Name, id1Key1.buf(), id1Key1.size(), make_shared<pib::PibMemory>());
+ key = Key(keyImpl);
BOOST_CHECK_EQUAL(static_cast<bool>(key), true);
BOOST_CHECK_EQUAL(!key, false);
@@ -62,27 +66,27 @@
BOOST_CHECK(false);
}
-BOOST_AUTO_TEST_CASE(CertificateOperations)
+/**
+ * pib::Key is a wrapper of pib::detail::KeyImpl. Since the functionalities of KeyImpl
+ * have already been tested in detail/key-impl.t.cpp, we only test the shared property
+ * of pib::Key in this test case.
+ */
+
+BOOST_AUTO_TEST_CASE(Share)
{
- Key key11(id1Key1Name, id1Key1.buf(), id1Key1.size(), make_shared<PibMemory>());
+ using security::pib::detail::KeyImpl;
- BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
- key11.addCertificate(id1Key1Cert1);
- BOOST_CHECK_NO_THROW(key11.getCertificate(id1Key1Cert1.getName()));
- key11.removeCertificate(id1Key1Cert1.getName());
- BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
+ auto keyImpl = make_shared<KeyImpl>(id1Key1Name, id1Key1.buf(), id1Key1.size(), make_shared<pib::PibMemory>());
+ Key key1(keyImpl);
+ Key key2(keyImpl);
- BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
- BOOST_REQUIRE_THROW(key11.setDefaultCertificate(id1Key1Cert1.getName()), Pib::Error);
- BOOST_REQUIRE_NO_THROW(key11.setDefaultCertificate(id1Key1Cert1));
- BOOST_REQUIRE_NO_THROW(key11.getDefaultCertificate());
+ key1.addCertificate(id1Key1Cert1);
+ BOOST_CHECK_NO_THROW(key2.getCertificate(id1Key1Cert1.getName()));
+ key2.removeCertificate(id1Key1Cert1.getName());
+ BOOST_CHECK_THROW(key1.getCertificate(id1Key1Cert1.getName()), Pib::Error);
- const auto& defaultCert = key11.getDefaultCertificate();
- BOOST_CHECK(defaultCert.wireEncode() == id1Key1Cert1.wireEncode());
-
- key11.removeCertificate(id1Key1Cert1.getName());
- BOOST_CHECK_THROW(key11.getCertificate(id1Key1Cert1.getName()), Pib::Error);
- BOOST_CHECK_THROW(key11.getDefaultCertificate(), Pib::Error);
+ key1.setDefaultCertificate(id1Key1Cert1);
+ BOOST_CHECK_NO_THROW(key2.getDefaultCertificate());
}
BOOST_AUTO_TEST_SUITE_END() // TestKey
diff --git a/tests/unit-tests/security/pib/pib-impl.t.cpp b/tests/unit-tests/security/pib/pib-impl.t.cpp
index 3103416..2677e9d 100644
--- a/tests/unit-tests/security/pib/pib-impl.t.cpp
+++ b/tests/unit-tests/security/pib/pib-impl.t.cpp
@@ -169,7 +169,7 @@
BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true);
const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name);
- BOOST_CHECK_EQUAL_COLLECTIONS(keyBits.begin(), keyBits.end(), this->id1Key1.begin(), this->id1Key1.end());
+ BOOST_CHECK(keyBits == this->id1Key1);
BOOST_CHECK_NO_THROW(this->pib.getDefaultKeyOfIdentity(this->id1));
BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name);
diff --git a/tests/unit-tests/security/pib/pib.t.cpp b/tests/unit-tests/security/pib/pib.t.cpp
index f947fed..de436b4 100644
--- a/tests/unit-tests/security/pib/pib.t.cpp
+++ b/tests/unit-tests/security/pib/pib.t.cpp
@@ -91,20 +91,46 @@
BOOST_AUTO_TEST_CASE(IdentityOperations)
{
Pib pib("pib-memory", "", make_shared<PibMemory>());
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 0);
+ // get non-existing identity, throw Pib::Error
BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
- Identity identity1 = pib.addIdentity(id1);
+ // get default identity when it is not set yet, throw Pib::Error
+ BOOST_CHECK_THROW(pib.getDefaultIdentity(), Pib::Error);
+
+ // add identity
+ pib.addIdentity(id1);
BOOST_CHECK_NO_THROW(pib.getIdentity(id1));
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 1);
+
+ // new key becomes default key when there was no default key
+ BOOST_REQUIRE_NO_THROW(pib.getDefaultIdentity());
+ BOOST_CHECK_EQUAL(pib.getDefaultIdentity().getName(), id1);
+
+ // remove identity
pib.removeIdentity(id1);
BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
-
BOOST_CHECK_THROW(pib.getDefaultIdentity(), Pib::Error);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 0);
+
+ // set default identity
BOOST_REQUIRE_NO_THROW(pib.setDefaultIdentity(id1));
BOOST_REQUIRE_NO_THROW(pib.getDefaultIdentity());
BOOST_CHECK_EQUAL(pib.getDefaultIdentity().getName(), id1);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 1);
+ BOOST_REQUIRE_NO_THROW(pib.setDefaultIdentity(id2));
+ BOOST_REQUIRE_NO_THROW(pib.getDefaultIdentity());
+ BOOST_CHECK_EQUAL(pib.getDefaultIdentity().getName(), id2);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 2);
+
+ // remove default identity
+ pib.removeIdentity(id2);
+ BOOST_CHECK_THROW(pib.getIdentity(id2), Pib::Error);
+ BOOST_CHECK_THROW(pib.getDefaultIdentity(), Pib::Error);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 1);
pib.removeIdentity(id1);
BOOST_CHECK_THROW(pib.getIdentity(id1), Pib::Error);
- BOOST_CHECK_THROW(pib.getDefaultIdentity(), Pib::Error);
+ BOOST_CHECK_EQUAL(pib.getIdentities().size(), 0);
}
BOOST_AUTO_TEST_SUITE_END() // TestPib