security: Split KeyChain into signing (KeyChain) and verification (Verifier) interfaces

This split removes the need for IdentityManager.

Also in this commit: Make verifySignature methods a set of static methods of Verifier.

Change-Id: Iea1c4353857a21417b2dcd1f91ba7013995d1459
diff --git a/include/ndn-cpp/security/key-chain.hpp b/include/ndn-cpp/security/key-chain.hpp
index 6d1e212..1dc8e7b 100644
--- a/include/ndn-cpp/security/key-chain.hpp
+++ b/include/ndn-cpp/security/key-chain.hpp
@@ -9,95 +9,231 @@
 #ifndef NDN_KEY_CHAIN_HPP
 #define NDN_KEY_CHAIN_HPP
 
-#include "../data.hpp"
-#include "../face.hpp"
-#include "identity/identity-manager.hpp"
-#include "encryption/encryption-manager.hpp"
-#include "policy/validation-request.hpp"
+#include "certificate/identity-certificate.hpp"
+#include "certificate/public-key.hpp"
+#include "identity/identity-storage.hpp"
+#include "identity/private-key-storage.hpp"
+
 
 namespace ndn {
 
-class PolicyManager;
-  
 /**
- * KeyChain is the main class of the security library.
+ * KeyChain is one of the main classes of the security library.
  *
- * The KeyChain class provides a set of interfaces to the security library such as identity management, policy configuration 
- * and packet signing and verification.
+ * The KeyChain class provides a set of interfaces of identity management and private key related operations.
  */
 class KeyChain {
 public:
   struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
 
   KeyChain(const ptr_lib::shared_ptr<IdentityStorage>   &identityStorage   = DefaultIdentityStorage,
-           const ptr_lib::shared_ptr<PrivateKeyStorage> &privateKeyStorage = DefaultPrivateKeyStorage,
-           const ptr_lib::shared_ptr<PolicyManager>     &policyManager     = DefaultPolicyManager,
-           const ptr_lib::shared_ptr<EncryptionManager> &encryptionManager = DefaultEncryptionManager);
+           const ptr_lib::shared_ptr<PrivateKeyStorage> &privateKeyStorage = DefaultPrivateKeyStorage);
+  
+  inline IdentityStorage&
+  info();
+
+  inline const IdentityStorage&
+  info() const;
+
+  inline PrivateKeyStorage&
+  tpm();
+
+  inline const PrivateKeyStorage&
+  tpm() const;
+
+  
+  /**
+   * Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a self-signed certificate of the KSK.
+   * @param identityName The name of the identity.
+   * @return The key name of the auto-generated KSK of the identity.
+   */
+  Name
+  createIdentity(const Name& identityName);
+    
+  /**
+   * Get the default identity.
+   * @return The default identity name.
+   */
+  Name
+  getDefaultIdentity()
+  {
+    return info().getDefaultIdentity();
+  }
+  
+  /**
+   * Generate a pair of RSA keys for the specified identity.
+   * @param identityName The name of the identity.
+   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
+   * @param keySize The size of the key.
+   * @return The generated key name.
+   */
+  Name
+  generateRSAKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
 
   /**
-   * @brief Set the Face which will be used to fetch required certificates.
-   * @param face A pointer to the Face object.
-   *
-   * Setting face is necessary for keychain operation that involve fetching data.
+   * Set a key as the default key of an identity.
+   * @param keyName The name of the key.
+   * @param identityName the name of the identity. If not specified, the identity name is inferred from the keyName.
    */
   void
-  setFace(const ptr_lib::shared_ptr<Face> &face) { face_ = face; }
+  setDefaultKeyForIdentity(const Name& keyName, const Name& identityName = Name())
+  {
+    info().setDefaultKeyNameForIdentity(keyName, identityName);
+    defaultCertificate_.reset();
+  }
+
+  /**
+   * Get the default key for an identity.
+   * @param identityName the name of the identity. If omitted, the identity name is inferred from the keyName.
+   * @return The default key name.
+   */
+  Name
+  getDefaultKeyNameForIdentity(const Name& identityName = Name())
+  {
+    return info().getDefaultKeyNameForIdentity(identityName);
+  }
   
-  /*****************************************
-   *          Identity Management          *
-   *****************************************/
+  /**
+   * Generate a pair of RSA keys for the specified identity and set it as default key for the identity.
+   * @param identityName The name of the identity.
+   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
+   * @param keySize The size of the key.
+   * @return The generated key name.
+   */
+  Name
+  generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
 
-  inline IdentityManager&
-  identities()
+  /**
+   * Get the public key with the specified name.
+   * @param keyName The name of the key.
+   * @return The public key.
+   */
+  ptr_lib::shared_ptr<PublicKey>
+  getPublicKey(const Name& keyName)
   {
-    if (!identityManager_)
-      throw Error("IdentityManager is not assigned to the KeyChain");
-
-    return *identityManager_;
+    return info().getKey(keyName);
   }
 
-  /*****************************************
-   *           Policy Management           *
-   *****************************************/
+  /**
+   * Create an identity certificate for a public key managed by this IdentityManager.
+   * @param certificatePrefix The name of public key to be signed.
+   * @param signerCertificateName The name of signing certificate.
+   * @param notBefore The notBefore value in the validity field of the generated certificate.
+   * @param notAfter The notAfter vallue in validity field of the generated certificate.
+   * @return The name of generated identity certificate.
+   */
+  ptr_lib::shared_ptr<IdentityCertificate>
+  createIdentityCertificate
+    (const Name& certificatePrefix,
+     const Name& signerCertificateName,
+     const MillisecondsSince1970& notBefore, 
+     const MillisecondsSince1970& notAfter);
 
-  inline PolicyManager&
-  policies()
+  /**
+   * Create an identity certificate for a public key supplied by the caller.
+   * @param certificatePrefix The name of public key to be signed.
+   * @param publickey The public key to be signed.
+   * @param signerCertificateName The name of signing certificate.
+   * @param notBefore The notBefore value in the validity field of the generated certificate.
+   * @param notAfter The notAfter vallue in validity field of the generated certificate.
+   * @return The generated identity certificate.
+   */
+  ptr_lib::shared_ptr<IdentityCertificate>
+  createIdentityCertificate
+    (const Name& certificatePrefix,
+     const PublicKey& publickey,
+     const Name& signerCertificateName, 
+     const MillisecondsSince1970& notBefore,
+     const MillisecondsSince1970& notAfter); 
+    
+  /**
+   * Add a certificate into the public key identity storage.
+   * @param certificate The certificate to to added.  This makes a copy of the certificate.
+   */
+  void
+  addCertificate(const IdentityCertificate& certificate)
   {
-    if (!policyManager_)
-      throw Error("PolicyManager is not assigned to the KeyChain");
-
-    return *policyManager_;
+    info().addCertificate(certificate);
   }
 
-  /*****************************************
-   *         Encryption Management         *
-   *****************************************/
+  /**
+   * Set the certificate as the default for its corresponding key.
+   * @param certificateName The certificate.
+   */
+  void
+  setDefaultCertificateForKey(const IdentityCertificate& certificate);
 
-  inline EncryptionManager&
-  encryption()
+  /**
+   * Add a certificate into the public key identity storage and set the certificate as the default for its corresponding identity.
+   * @param certificate The certificate to be added.  This makes a copy of the certificate.
+   */
+  void
+  addCertificateAsIdentityDefault(const IdentityCertificate& certificate);
+
+  /**
+   * Add a certificate into the public key identity storage and set the certificate as the default of its corresponding key.
+   * @param certificate The certificate to be added.  This makes a copy of the certificate.
+   */
+  void
+  addCertificateAsDefault(const IdentityCertificate& certificate);
+
+  /**
+   * Get a certificate with the specified name.
+   * @param certificateName The name of the requested certificate.
+   * @return the requested certificate which is valid.
+   */
+  ptr_lib::shared_ptr<IdentityCertificate>
+  getCertificate(const Name& certificateName)
   {
-    if (!encryptionManager_)
-      throw Error("EncryptionManager is not assigned to the KeyChain");
-
-    return *encryptionManager_;
+    return info().getCertificate(certificateName, false);
+  }
+    
+  /**
+   * Get a certificate even if the certificate is not valid anymore.
+   * @param certificateName The name of the requested certificate.
+   * @return the requested certificate.
+   */
+  ptr_lib::shared_ptr<IdentityCertificate>
+  getAnyCertificate(const Name& certificateName)
+  {
+    return info().getCertificate(certificateName, true);
+  }
+    
+  /**
+   * Get the default certificate name for the specified identity, which will be used when signing is performed based on identity.
+   * @param identityName The name of the specified identity.
+   * @return The requested certificate name.
+   */
+  Name
+  getDefaultCertificateNameForIdentity(const Name& identityName)
+  {
+    return info().getDefaultCertificateNameForIdentity(identityName);
+  }
+    
+  /**
+   * Get the default certificate name of the default identity, which will be used when signing is based on identity and 
+   * the identity is not specified.
+   * @return The requested certificate name.
+   */
+  Name
+  getDefaultCertificateName()
+  {
+    return info().getDefaultCertificateNameForIdentity(getDefaultIdentity());
   }
 
-  /*****************************************
-   *              Sign/Verify              *
-   *****************************************/
-
-  inline void 
-  sign(Data& data);
+  void
+  sign(Data &data);
   
   /**
    * Wire encode the Data object, sign it and set its signature.
-   * Note: the caller must make sure the timestamp is correct, for example with 
-   * data.getMetaInfo().setTimestampMilliseconds(time(NULL) * 1000.0).
    * @param data The Data object to be signed.  This updates its signature and key locator field and wireEncoding.
    * @param certificateName The certificate name of the key to use for signing.  If omitted, infer the signing identity from the data packet name.
    */
-  inline void 
+  void 
   sign(Data& data, const Name& certificateName);
+
+  void
+  sign(Data& data, const IdentityCertificate& certificate);
   
   /**
    * Sign the byte array using a certificate name and return a Signature object.
@@ -106,13 +242,11 @@
    * @param certificateName The certificate name used to get the signing key and which will be put into KeyLocator.
    * @return The Signature.
    */
-  inline Signature
+  Signature
   sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
 
   /**
    * Wire encode the Data object, sign it and set its signature.
-   * Note: the caller must make sure the timestamp is correct, for example with 
-   * data.getMetaInfo().setTimestampMilliseconds(time(NULL) * 1000.0).
    * @param data The Data object to be signed.  This updates its signature and key locator field and wireEncoding.
    * @param identityName The identity name for the key to use for signing.  If omitted, infer the signing identity from the data packet name.
    */
@@ -127,70 +261,82 @@
    * @return The Signature.
    */
   Signature
-  signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
+  signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName = Name());
 
   /**
-   * Check the signature on the Data object and call either onVerify or onVerifyFailed. 
-   * We use callback functions because verify may fetch information to check the signature.
-   * @param data The Data object with the signature to check. It is an error if data does not have a wireEncoding. 
-   * To set the wireEncoding, you can call data.wireDecode.
-   * @param onVerified If the signature is verified, this calls onVerified(data).
-   * @param onVerifyFailed If the signature check fails, this calls onVerifyFailed(data).
+   * Generate a self-signed certificate for a public key.
+   * @param keyName The name of the public key.
+   * @return The generated certificate.
+   */
+  ptr_lib::shared_ptr<IdentityCertificate>
+  selfSign(const Name& keyName);
+
+  /**
+   * @brief Self-sign the supplied identity certificate
    */
   void
-  verifyData
-    (const ptr_lib::shared_ptr<Data>& data, const OnVerified& onVerified, const OnVerifyFailed& onVerifyFailed, int stepCount = 0);
+  selfSign (IdentityCertificate& cert);
 
-  /*****************************************
-   *           Encrypt/Decrypt             *
-   *****************************************/
-  // todo
+private:
+  /**
+   * Generate a key pair for the specified identity.
+   * @param identityName The name of the specified identity.
+   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
+   * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
+   * @param keySize The size of the key pair.
+   * @return The name of the generated key.
+   */
+  Name
+  generateKeyPair(const Name& identityName, bool isKsk = false, KeyType keyType = KEY_TYPE_RSA, int keySize = 2048);
+
+  static Name
+  getKeyNameFromCertificatePrefix(const Name& certificatePrefix);
 
 public:
   static const ptr_lib::shared_ptr<IdentityStorage>   DefaultIdentityStorage;
   static const ptr_lib::shared_ptr<PrivateKeyStorage> DefaultPrivateKeyStorage;
-  static const ptr_lib::shared_ptr<PolicyManager>     DefaultPolicyManager;
-  static const ptr_lib::shared_ptr<EncryptionManager> DefaultEncryptionManager;
     
 private:
-  void
-  onCertificateData
-    (const ptr_lib::shared_ptr<const Interest> &interest, const ptr_lib::shared_ptr<Data> &data, ptr_lib::shared_ptr<ValidationRequest> nextStep);
-  
-  void
-  onCertificateInterestTimeout
-    (const ptr_lib::shared_ptr<const Interest> &interest, int retry, const OnVerifyFailed& onVerifyFailed, 
-     const ptr_lib::shared_ptr<Data> &data, ptr_lib::shared_ptr<ValidationRequest> nextStep);
-
-private:
   ptr_lib::shared_ptr<IdentityStorage>   publicInfoStorage_;
   ptr_lib::shared_ptr<PrivateKeyStorage> privateKeyStorage_;
-  ptr_lib::shared_ptr<IdentityManager>   identityManager_; // uses publicInfo and privateKey storages
 
-  ptr_lib::shared_ptr<PolicyManager>     policyManager_;
-  ptr_lib::shared_ptr<EncryptionManager> encryptionManager_;
-
-  ptr_lib::shared_ptr<Face>        face_;
-  
-  // const int maxSteps_;
+  ptr_lib::shared_ptr<IdentityCertificate> defaultCertificate_;
 };
 
-void 
-KeyChain::sign(Data& data)
+
+inline IdentityStorage&
+KeyChain::info()
 {
-  identities().sign(data);
+  if (!publicInfoStorage_)
+    throw Error("IdentityStorage is not assigned to IdentityManager");
+
+  return *publicInfoStorage_;
 }
 
-void 
-KeyChain::sign(Data& data, const Name& certificateName)
+inline const IdentityStorage&
+KeyChain::info() const
 {
-  identities().signByCertificate(data, certificateName);
+  if (!publicInfoStorage_)
+    throw Error("IdentityStorage is not assigned to IdentityManager");
+  
+  return *publicInfoStorage_;
 }
 
-Signature
-KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
+inline PrivateKeyStorage&
+KeyChain::tpm()
 {
-  return identities().signByCertificate(buffer, bufferLength, certificateName);
+  if (!privateKeyStorage_)
+    throw Error("PrivateKeyStorage is not assigned to IdentityManager");
+  
+  return *privateKeyStorage_;
+}
+
+inline const PrivateKeyStorage&
+KeyChain::tpm() const
+{
+  if (!privateKeyStorage_)
+    throw Error("PrivateKeyStorage is not assigned to IdentityManager");
+  return *privateKeyStorage_;
 }
 
 }