security: Add ECDSA signature signing and validation

Change-Id: I2f193e9d643498a68579ae59a7f524ff446dcb9e
Refs: #1660
diff --git a/src/security/cryptopp.hpp b/src/security/cryptopp.hpp
index 3aac257..d7342cf 100644
--- a/src/security/cryptopp.hpp
+++ b/src/security/cryptopp.hpp
@@ -38,5 +38,8 @@
 #include <cryptopp/pwdbased.h>
 #include <cryptopp/rsa.h>
 #include <cryptopp/sha.h>
+#include <cryptopp/eccrypto.h>
+#include <cryptopp/oids.h>
+#include <cryptopp/dsa.h>
 
 #endif // NDN_SECURITY_CRYPTOPP_HPP
diff --git a/src/security/key-chain.cpp b/src/security/key-chain.cpp
index a04e58b..69d5b48 100644
--- a/src/security/key-chain.cpp
+++ b/src/security/key-chain.cpp
@@ -131,6 +131,14 @@
   try
     {
       keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
+
+      shared_ptr<PublicKey> key = m_pib->getPublicKey(keyName);
+
+      if (key->getKeyType() != params.getKeyType())
+        {
+          keyName = generateKeyPair(identityName, true, params);
+          m_pib->setDefaultKeyNameForIdentity(keyName);
+        }
     }
   catch (SecPublicInfo::Error& e)
     {
@@ -154,7 +162,7 @@
 }
 
 Name
-KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
+KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
 {
   RsaKeyParams params(keySize);
 
@@ -165,6 +173,19 @@
   return keyName;
 }
 
+Name
+KeyChain::generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+  EcdsaKeyParams params(keySize);
+
+  Name keyName = generateKeyPair(identityName, isKsk, params);
+
+  m_pib->setDefaultKeyNameForIdentity(keyName);
+
+  return keyName;
+}
+
+
 shared_ptr<IdentityCertificate>
 KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
   const Name& signingIdentity,
@@ -266,19 +287,21 @@
 Signature
 KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
 {
-  if (!m_pib->doesCertificateExist(certificateName))
-    throw SecPublicInfo::Error("Requested certificate [" +
-                               certificateName.toUri() + "] doesn't exist");
+  shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
 
-  Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
+  shared_ptr<SignatureWithPublicKey> sig =
+    determineSignatureWithPublicKey(certificate->getPublicKeyInfo().getKeyType());
 
-  SignatureSha256WithRsa signature;
-  // implicit conversion should take care
-  signature.setKeyLocator(certificateName.getPrefix(-1));
+  if (!static_cast<bool>(sig))
+    throw SecTpm::Error("unknown key type");
 
-  // For temporary usage, we support RSA + SHA256 only, but will support more.
-  signature.setValue(m_tpm->signInTpm(buffer, bufferLength, keyName, DIGEST_ALGORITHM_SHA256));
-  return signature;
+  sig->setKeyLocator(certificate->getName().getPrefix(-1));
+  // For temporary usage, we support SHA256 only, but will support more.
+  sig->setValue(m_tpm->signInTpm(buffer, bufferLength,
+                                 certificate->getPublicKeyName(),
+                                 DIGEST_ALGORITHM_SHA256));
+
+  return *sig;
 }
 
 shared_ptr<IdentityCertificate>
@@ -317,11 +340,14 @@
   if (!m_tpm->doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
     throw SecTpm::Error("Private key does not exist");
 
-  SignatureSha256WithRsa signature;
-  signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
+  shared_ptr<SignatureWithPublicKey> sig =
+    determineSignatureWithPublicKey(cert.getPublicKeyInfo().getKeyType());
 
-  // For temporary usage, we support RSA + SHA256 only, but will support more.
-  signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
+  if (!static_cast<bool>(sig))
+    throw SecTpm::Error("unknown key type");
+
+  sig->setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
+  signPacketWrapper(cert, *sig, keyName, DIGEST_ALGORITHM_SHA256);
 }
 
 shared_ptr<SecuredBag>
@@ -384,6 +410,32 @@
   m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
 }
 
+shared_ptr<SignatureWithPublicKey>
+KeyChain::determineSignatureWithPublicKey(KeyType keyType, DigestAlgorithm digestAlgorithm)
+{
+  switch (keyType)
+    {
+    case KEY_TYPE_RSA:
+      {
+        // For temporary usage, we support SHA256 only, but will support more.
+        if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
+          return shared_ptr<SignatureWithPublicKey>();
+
+        return make_shared<SignatureSha256WithRsa>();
+      }
+    case KEY_TYPE_ECDSA:
+      {
+        // For temporary usage, we support SHA256 only, but will support more.
+        if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
+          return shared_ptr<SignatureWithPublicKey>();
+
+        return make_shared<SignatureSha256WithEcdsa>();
+      }
+    default:
+      return shared_ptr<SignatureWithPublicKey>();
+    }
+}
+
 void
 KeyChain::setDefaultCertificateInternal()
 {
@@ -422,7 +474,7 @@
 }
 
 void
-KeyChain::signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
+KeyChain::signPacketWrapper(Data& data, const Signature& signature,
                             const Name& keyName, DigestAlgorithm digestAlgorithm)
 {
   data.setSignature(signature);
@@ -436,7 +488,7 @@
 }
 
 void
-KeyChain::signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
+KeyChain::signPacketWrapper(Interest& interest, const Signature& signature,
                             const Name& keyName, DigestAlgorithm digestAlgorithm)
 {
   time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index 44ff1de..b6b9bbf 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -29,6 +29,7 @@
 #include "key-params.hpp"
 #include "secured-bag.hpp"
 #include "signature-sha256-with-rsa.hpp"
+#include "signature-sha256-with-ecdsa.hpp"
 #include "digest-sha256.hpp"
 
 #include "../interest.hpp"
@@ -103,8 +104,10 @@
    * @return The generated key name.
    */
   inline Name
-  generateRsaKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
+  generateRsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 2048);
 
+  inline Name
+  generateEcdsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 256);
   /**
    * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
    *        the identity.
@@ -115,7 +118,11 @@
    * @return The generated key name.
    */
   Name
-  generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
+  generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false,
+                              uint32_t keySize = 2048);
+
+  Name
+  generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize = 256);
 
   /**
    * @brief prepare an unsigned identity certificate
@@ -635,6 +642,15 @@
 
 private:
   /**
+   * @brief Determine signature type
+   *
+   * An empty pointer will be returned if there is no valid signature.
+   */
+  shared_ptr<SignatureWithPublicKey>
+  determineSignatureWithPublicKey(KeyType keyType,
+                                  DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256);
+
+  /**
    * @brief Set default certificate if it is not initialized
    */
   void
@@ -672,7 +688,7 @@
    * @throws Tpm::Error
    */
   void
-  signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
+  signPacketWrapper(Data& data, const Signature& signature,
                     const Name& keyName, DigestAlgorithm digestAlgorithm);
 
   /**
@@ -685,7 +701,7 @@
    * @throws Tpm::Error
    */
   void
-  signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
+  signPacketWrapper(Interest& interest, const Signature& signature,
                     const Name& keyName, DigestAlgorithm digestAlgorithm);
 
 
@@ -705,12 +721,19 @@
 }
 
 inline Name
-KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, int keySize)
+KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
 {
   RsaKeyParams params(keySize);
   return generateKeyPair(identityName, isKsk, params);
 }
 
+inline Name
+KeyChain::generateEcdsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+  EcdsaKeyParams params(keySize);
+  return generateKeyPair(identityName, isKsk, params);
+}
+
 template<typename T>
 void
 KeyChain::sign(T& packet)
@@ -725,18 +748,8 @@
 void
 KeyChain::sign(T& packet, const Name& certificateName)
 {
-  if (!m_pib->doesCertificateExist(certificateName))
-    throw SecPublicInfo::Error("Requested certificate [" +
-                               certificateName.toUri() + "] doesn't exist");
-
-  SignatureSha256WithRsa signature;
-  // implicit conversion should take care
-  signature.setKeyLocator(certificateName.getPrefix(-1));
-
-  // For temporary usage, we support RSA + SHA256 only, but will support more.
-  signPacketWrapper(packet, signature,
-                    IdentityCertificate::certificateNameToPublicKeyName(certificateName),
-                    DIGEST_ALGORITHM_SHA256);
+  shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
+  sign(packet, *certificate);
 }
 
 template<typename T>
@@ -764,11 +777,35 @@
 void
 KeyChain::sign(T& packet, const IdentityCertificate& certificate)
 {
-  SignatureSha256WithRsa signature;
-  signature.setKeyLocator(certificate.getName().getPrefix(-1));
+  switch (certificate.getPublicKeyInfo().getKeyType())
+    {
+    case KEY_TYPE_RSA:
+      {
+        // For temporary usage, we support SHA256 only, but will support more.
+        SignatureSha256WithRsa signature;
+        // implicit conversion should take care
+        signature.setKeyLocator(certificate.getName().getPrefix(-1));
 
-  // For temporary usage, we support RSA + SHA256 only, but will support more.
-  signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
+        signPacketWrapper(packet, signature,
+                          certificate.getPublicKeyName(),
+                          DIGEST_ALGORITHM_SHA256);
+        return;
+      }
+    case KEY_TYPE_ECDSA:
+      {
+        // For temporary usage, we support SHA256 only, but will support more.
+        SignatureSha256WithEcdsa signature;
+        // implicit conversion should take care
+        signature.setKeyLocator(certificate.getName().getPrefix(-1));
+
+        signPacketWrapper(packet, signature,
+                          certificate.getPublicKeyName(),
+                          DIGEST_ALGORITHM_SHA256);
+        return;
+      }
+    default:
+      throw SecPublicInfo::Error("unknown key type!");
+    }
 }
 
 }
diff --git a/src/security/sec-public-info-sqlite3.cpp b/src/security/sec-public-info-sqlite3.cpp
index a690bef..7e86773 100644
--- a/src/security/sec-public-info-sqlite3.cpp
+++ b/src/security/sec-public-info-sqlite3.cpp
@@ -27,6 +27,7 @@
 #include "sec-public-info-sqlite3.hpp"
 #include "identity-certificate.hpp"
 #include "signature-sha256-with-rsa.hpp"
+#include "signature-sha256-with-ecdsa.hpp"
 #include "../data.hpp"
 
 #include <sqlite3.h>
@@ -479,10 +480,27 @@
     {
       // this will throw an exception if the signature is not the standard one
       // or there is no key locator present
-      SignatureSha256WithRsa signature(certificate.getSignature());
-      std::string signerName = signature.getKeyLocator().getName().toUri();
+      switch (certificate.getSignature().getType())
+        {
+        case Tlv::SignatureSha256WithRsa:
+          {
+            SignatureSha256WithRsa signature(certificate.getSignature());
+            std::string signerName = signature.getKeyLocator().getName().toUri();
 
-      sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
+            sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
+            break;
+          }
+        case Tlv::SignatureSha256WithEcdsa:
+          {
+            SignatureSha256WithEcdsa signature(certificate.getSignature());
+            std::string signerName = signature.getKeyLocator().getName().toUri();
+
+            sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
+            break;
+          }
+        default:
+          return;
+        }
     }
   catch (std::runtime_error& e)
     {
diff --git a/src/security/sec-tpm-file.cpp b/src/security/sec-tpm-file.cpp
index 6634f68..03ce634 100644
--- a/src/security/sec-tpm-file.cpp
+++ b/src/security/sec-tpm-file.cpp
@@ -142,6 +142,51 @@
             chmod(publicKeyFileName.c_str(), 0000444);
             return;
           }
+        case KEY_TYPE_ECDSA:
+          {
+            using namespace CryptoPP;
+
+            const EcdsaKeyParams& ecdsaParams = static_cast<const EcdsaKeyParams&>(params);
+
+            OID curveName;
+            switch (ecdsaParams.getKeySize())
+              {
+              case 256:
+                curveName = ASN1::secp256r1();
+                break;
+              case 384:
+                curveName = ASN1::secp384r1();
+                break;
+              default:
+                curveName = ASN1::secp256r1();
+              }
+
+            AutoSeededRandomPool rng;
+
+            ECDSA<ECP, SHA256>::PrivateKey privateKey;
+            DL_GroupParameters_EC<ECP> cryptoParams(curveName);
+            cryptoParams.SetEncodeAsOID(true);
+            privateKey.Initialize(rng, cryptoParams);
+
+            ECDSA<ECP, SHA256>::PublicKey publicKey;
+            privateKey.MakePublicKey(publicKey);
+            publicKey.AccessGroupParameters().SetEncodeAsOID(true);
+
+            string privateKeyFileName = keyFileName + ".pri";
+            Base64Encoder privateKeySink(new FileSink(privateKeyFileName.c_str()));
+            privateKey.DEREncode(privateKeySink);
+            privateKeySink.MessageEnd();
+
+            string publicKeyFileName = keyFileName + ".pub";
+            Base64Encoder publicKeySink(new FileSink(publicKeyFileName.c_str()));
+            publicKey.Save(publicKeySink);
+            publicKeySink.MessageEnd();
+
+            /*set file permission*/
+            chmod(privateKeyFileName.c_str(), 0000400);
+            chmod(publicKeyFileName.c_str(), 0000444);
+            return;
+          }
         default:
           throw Error("Unsupported key type!");
         }
@@ -258,31 +303,79 @@
       using namespace CryptoPP;
       AutoSeededRandomPool rng;
 
-      //Read private key
-      ByteQueue bytes;
-      FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(),
-                      true, new Base64Decoder);
-      file.TransferTo(bytes);
-      bytes.MessageEnd();
-      RSA::PrivateKey privateKey;
-      privateKey.Load(bytes);
+      //Read public key
+      shared_ptr<PublicKey> pubkeyPtr;
+      pubkeyPtr = getPublicKeyFromTpm(keyName);
 
-      //Sign message
-      switch (digestAlgorithm)
+      switch (pubkeyPtr->getKeyType())
         {
-        case DIGEST_ALGORITHM_SHA256:
+          case KEY_TYPE_RSA:
+            {
+              //Read private key
+              ByteQueue bytes;
+              FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(),
+                              true, new Base64Decoder);
+              file.TransferTo(bytes);
+              bytes.MessageEnd();
+              RSA::PrivateKey privateKey;
+              privateKey.Load(bytes);
+
+              //Sign message
+              switch (digestAlgorithm)
+                {
+                case DIGEST_ALGORITHM_SHA256:
+                  {
+                    RSASS<PKCS1v15, SHA256>::Signer signer(privateKey);
+
+                    OBufferStream os;
+                    StringSource(data, dataLength,
+                                 true,
+                                 new SignerFilter(rng, signer, new FileSink(os)));
+
+                    return Block(Tlv::SignatureValue, os.buf());
+                  }
+                default:
+                  throw Error("Unsupported digest algorithm!");
+                }
+            }
+        case KEY_TYPE_ECDSA:
           {
-            RSASS<PKCS1v15, SHA256>::Signer signer(privateKey);
+            //Read private key
+            ByteQueue bytes;
+            FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(),
+                            true, new Base64Decoder);
+            file.TransferTo(bytes);
+            bytes.MessageEnd();
 
-            OBufferStream os;
-            StringSource(data, dataLength,
-                         true,
-                         new SignerFilter(rng, signer, new FileSink(os)));
+            //Sign message
+            switch (digestAlgorithm)
+              {
+              case DIGEST_ALGORITHM_SHA256:
+                {
+                  ECDSA<ECP, SHA256>::PrivateKey privateKey;
+                  privateKey.Load(bytes);
+                  ECDSA<ECP, SHA256>::Signer signer(privateKey);
 
-            return Block(Tlv::SignatureValue, os.buf());
+                  OBufferStream os;
+                  StringSource(data, dataLength,
+                               true,
+                               new SignerFilter(rng, signer, new FileSink(os)));
+
+                  uint8_t buf[200];
+                  size_t bufSize = DSAConvertSignatureFormat(buf, 200, DSA_DER,
+                                                             os.buf()->buf(), os.buf()->size(),
+                                                             DSA_P1363);
+
+                  shared_ptr<Buffer> sigBuffer = make_shared<Buffer>(buf, bufSize);
+
+                  return Block(Tlv::SignatureValue, sigBuffer);
+                }
+              default:
+                throw Error("Unsupported digest algorithm!");
+              }
           }
         default:
-          throw Error("Unsupported digest algorithm!");
+          throw Error("Unsupported key type!");
         }
     }
   catch (CryptoPP::Exception& e)
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index 031632d..f3a782bc 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -396,6 +396,12 @@
         keySize = rsaParams.getKeySize();
         break;
       }
+    case KEY_TYPE_ECDSA:
+      {
+        const EcdsaKeyParams& ecdsaParams = static_cast<const EcdsaKeyParams&>(params);
+        keySize = ecdsaParams.getKeySize();
+        break;
+      }
     default:
       throw Error("Fail to create a key pair: Unsupported key type");
     }
@@ -1039,6 +1045,8 @@
   switch (keyType) {
   case KEY_TYPE_RSA:
     return kSecAttrKeyTypeRSA;
+  case KEY_TYPE_ECDSA:
+    return kSecAttrKeyTypeECDSA;
   default:
     return 0;
   }
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index 29a4801..df7b0e6 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -29,10 +29,11 @@
 
 #include "cryptopp.hpp"
 
-using namespace std;
-
 namespace ndn {
 
+static OID SECP256R1("1.2.840.10045.3.1.7");
+static OID SECP384R1("1.3.132.0.34");
+
 Validator::Validator()
   : m_hasFace(false)
   , m_face(*static_cast<Face*>(0))
@@ -51,7 +52,7 @@
                     const OnInterestValidationFailed& onValidationFailed,
                     int nSteps)
 {
-  vector<shared_ptr<ValidationRequest> > nextSteps;
+  std::vector<shared_ptr<ValidationRequest> > nextSteps;
   checkPolicy(interest, nSteps, onValidated, onValidationFailed, nextSteps);
 
   if (!nextSteps.empty())
@@ -63,7 +64,7 @@
           return;
         }
 
-      vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
+      std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
       OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
       for (; it != nextSteps.end(); it++)
         m_face.expressInterest((*it)->m_interest,
@@ -87,7 +88,7 @@
                     const OnDataValidationFailed& onValidationFailed,
                     int nSteps)
 {
-  vector<shared_ptr<ValidationRequest> > nextSteps;
+  std::vector<shared_ptr<ValidationRequest> > nextSteps;
   checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
 
   if (!nextSteps.empty())
@@ -98,7 +99,7 @@
                              "Require more information to validate the data!");
         }
 
-      vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
+      std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
       OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
       for (; it != nextSteps.end(); it++)
         m_face.expressInterest((*it)->m_interest,
@@ -147,13 +148,25 @@
     {
       switch (data.getSignature().getType())
         {
-        case Signature::Sha256WithRsa:
+        case Tlv::SignatureSha256WithRsa:
           {
             SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
-            return verifySignature(data, sigSha256Rsa, key);
+            return verifySignature(data.wireEncode().value(),
+                                   data.wireEncode().value_size() -
+                                   data.getSignature().getValue().size(),
+                                   sigSha256Rsa, key);
           }
+        case Tlv::SignatureSha256WithEcdsa:
+          {
+            SignatureSha256WithEcdsa sigSha256Ecdsa(data.getSignature());
+            return verifySignature(data.wireEncode().value(),
+                                   data.wireEncode().value_size() -
+                                   data.getSignature().getValue().size(),
+                                   sigSha256Ecdsa, key);
+           }
         default:
           {
+            // Unsupported sig type
             return false;
           }
         }
@@ -182,7 +195,7 @@
 
       switch (sig.getType())
         {
-        case Signature::Sha256WithRsa:
+        case Tlv::SignatureSha256WithRsa:
           {
             SignatureSha256WithRsa sigSha256Rsa(sig);
 
@@ -190,8 +203,17 @@
                                    nameBlock.value_size() - interestName[-1].size(),
                                    sigSha256Rsa, key);
           }
+        case Tlv::SignatureSha256WithEcdsa:
+          {
+            SignatureSha256WithEcdsa sigSha256Ecdsa(sig);
+
+            return verifySignature(nameBlock.value(),
+                                   nameBlock.value_size() - interestName[-1].size(),
+                                   sigSha256Ecdsa, key);
+          }
         default:
           {
+            // Unsupported sig type
             return false;
           }
         }
@@ -208,50 +230,94 @@
 }
 
 bool
-Validator::verifySignature(const Buffer& data, const Signature& sig, const PublicKey& key)
-{
-  try
-    {
-      switch (sig.getType())
-        {
-        case Signature::Sha256WithRsa:
-          {
-            SignatureSha256WithRsa sigSha256Rsa(sig);
-            return verifySignature(data, sigSha256Rsa, key);
-          }
-        default:
-          {
-            return false;
-          }
-        }
-    }
-  catch (Signature::Error& e)
-    {
-      return false;
-    }
-  return false;
-}
-
-bool
 Validator::verifySignature(const uint8_t* buf,
                            const size_t size,
-                           const SignatureSha256WithRsa& sig,
+                           const SignatureWithPublicKey& sig,
                            const PublicKey& key)
 {
   try
     {
       using namespace CryptoPP;
 
-      RSA::PublicKey publicKey;
-      ByteQueue queue;
+      switch (sig.getType())
+        {
+        case Tlv::SignatureSha256WithRsa:
+          {
+            if (key.getKeyType() != KEY_TYPE_RSA)
+              return false;
 
-      queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
-      publicKey.Load(queue);
+            RSA::PublicKey publicKey;
+            ByteQueue queue;
 
-      RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
-      return verifier.VerifyMessage(buf, size,
-                                    sig.getValue().value(),
-                                    sig.getValue().value_size());
+            queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
+            publicKey.Load(queue);
+
+            RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
+            return verifier.VerifyMessage(buf, size,
+                                          sig.getValue().value(), sig.getValue().value_size());
+          }
+        case Tlv::SignatureSha256WithEcdsa:
+          {
+            if (key.getKeyType() != KEY_TYPE_ECDSA)
+              return false;
+
+            ECDSA<ECP, SHA256>::PublicKey publicKey;
+            ByteQueue queue;
+
+            queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
+            publicKey.Load(queue);
+
+            ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+
+            uint32_t length = 0;
+            StringSource src(key.get().buf(), key.get().size(), true);
+            BERSequenceDecoder subjectPublicKeyInfo(src);
+            {
+              BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
+              {
+                OID algorithm;
+                algorithm.decode(algorithmInfo);
+
+                OID curveId;
+                curveId.decode(algorithmInfo);
+
+                if (curveId == SECP256R1)
+                  length = 256;
+                else if (curveId == SECP384R1)
+                  length = 384;
+                else
+                  return false;
+              }
+            }
+
+            switch (length)
+              {
+              case 256:
+                {
+                  uint8_t buffer[64];
+                  size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                              sig.getValue().value(),
+                                                              sig.getValue().value_size(),
+                                                              DSA_DER);
+                  return verifier.VerifyMessage(buf, size, buffer, usedSize);
+                }
+              case 384:
+                {
+                  uint8_t buffer[96];
+                  size_t usedSize = DSAConvertSignatureFormat(buffer, 96, DSA_P1363,
+                                                              sig.getValue().value(),
+                                                              sig.getValue().value_size(),
+                                                              DSA_DER);
+                  return verifier.VerifyMessage(buf, size, buffer, usedSize);
+                }
+              default:
+                return false;
+              }
+          }
+        default:
+          // Unsupported sig type
+          return false;
+        }
     }
   catch (CryptoPP::Exception& e)
     {
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index 5d66367..87c2bfd 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -31,6 +31,7 @@
 #include "../face.hpp"
 #include "public-key.hpp"
 #include "signature-sha256-with-rsa.hpp"
+#include "signature-sha256-with-ecdsa.hpp"
 #include "digest-sha256.hpp"
 #include "validation-request.hpp"
 
@@ -106,12 +107,15 @@
 
   /// @brief Verify the blob using the publicKey against the signature.
   static bool
-  verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey);
+  verifySignature(const Buffer& blob, const SignatureWithPublicKey& sig, const PublicKey& publicKey)
+  {
+    return verifySignature(blob.buf(), blob.size(), sig, publicKey);
+  }
 
   /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
   static bool
   verifySignature(const Data& data,
-                  const SignatureSha256WithRsa& sig,
+                  const SignatureWithPublicKey& sig,
                   const PublicKey& publicKey)
   {
     return verifySignature(data.wireEncode().value(),
@@ -125,7 +129,7 @@
    */
   static bool
   verifySignature(const Interest& interest,
-                  const SignatureSha256WithRsa& sig,
+                  const SignatureWithPublicKey& sig,
                   const PublicKey& publicKey)
   {
     if (interest.getName().size() < 2)
@@ -140,18 +144,9 @@
 
   /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
   static bool
-  verifySignature(const Buffer& blob,
-                  const SignatureSha256WithRsa& sig,
-                  const PublicKey& publicKey)
-  {
-    return verifySignature(blob.buf(), blob.size(), sig, publicKey);
-  }
-
-  /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
-  static bool
   verifySignature(const uint8_t* buf,
                   const size_t size,
-                  const SignatureSha256WithRsa& sig,
+                  const SignatureWithPublicKey& sig,
                   const PublicKey& publicKey);
 
 
diff --git a/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp b/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp
index 547eac0..6d44811 100644
--- a/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp
+++ b/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp
@@ -121,11 +121,13 @@
   shared_ptr<PublicKey> rsaKey;
   BOOST_REQUIRE_NO_THROW(rsaKey = shared_ptr<PublicKey>(new PublicKey(os.buf()->buf(),
                                                                       os.buf()->size())));
-  Name rsaKeyName("/TestSecPublicInfoSqlite3/KeyType/RSA");
+  Name rsaKeyName("/TestSecPublicInfoSqlite3/KeyType/RSA/ksk-123");
   SecPublicInfoSqlite3 pib;
   pib.addPublicKey(rsaKeyName, rsaKey->getKeyType(), *rsaKey);
 
   BOOST_CHECK_EQUAL(KEY_TYPE_RSA, pib.getPublicKeyType(rsaKeyName));
+
+  pib.deleteIdentityInfo(Name("/TestSecPublicInfoSqlite3/KeyType/RSA"));
 }
 
 BOOST_AUTO_TEST_CASE(KeyTypeEcdsa)
@@ -139,12 +141,12 @@
   shared_ptr<PublicKey> ecdsaKey;
   BOOST_REQUIRE_NO_THROW(ecdsaKey = shared_ptr<PublicKey>(new PublicKey(os.buf()->buf(),
                                                                         os.buf()->size())));
-  Name ecdsaKeyName("/TestSecPublicInfoSqlite3/KeyType/ECDSA");
+  Name ecdsaKeyName("/TestSecPublicInfoSqlite3/KeyType/ECDSA/ksk-123");
   SecPublicInfoSqlite3 pib;
   pib.addPublicKey(ecdsaKeyName, ecdsaKey->getKeyType(), *ecdsaKey);
 
   BOOST_CHECK_EQUAL(KEY_TYPE_ECDSA, pib.getPublicKeyType(ecdsaKeyName));
-
+  pib.deleteIdentityInfo(Name("/TestSecPublicInfoSqlite3/KeyType/ECDSA"));
 }
 
 BOOST_AUTO_TEST_CASE(KeyTypeNonExist)
diff --git a/tests/unit-tests/security/test-sec-tpm-file.cpp b/tests/unit-tests/security/test-sec-tpm-file.cpp
index bcfcec0..c25a40b 100644
--- a/tests/unit-tests/security/test-sec-tpm-file.cpp
+++ b/tests/unit-tests/security/test-sec-tpm-file.cpp
@@ -243,6 +243,52 @@
   BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
 }
 
+BOOST_AUTO_TEST_CASE(EcdsaSigning)
+{
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/EcdsaSigning/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+  EcdsaKeyParams params;
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  Data data("/TestSecTpmFile/EcdsaSigning/Data/1");
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DIGEST_ALGORITHM_SHA256));
+
+  shared_ptr<PublicKey> pubkeyPtr;
+  BOOST_CHECK_NO_THROW(pubkeyPtr = tpm.getPublicKeyFromTpm(keyName));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey publicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+      publicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock.value(), sigBlock.value_size(), DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+      bool result = verifier.VerifyMessage(content, sizeof(content),
+                                           buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(result, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace ndn
diff --git a/tests/unit-tests/security/test-sec-tpm-osx.cpp b/tests/unit-tests/security/test-sec-tpm-osx.cpp
index da92cc9..3b28c66 100644
--- a/tests/unit-tests/security/test-sec-tpm-osx.cpp
+++ b/tests/unit-tests/security/test-sec-tpm-osx.cpp
@@ -200,6 +200,51 @@
                       SecTpmOsx::Error);
 }
 
+BOOST_AUTO_TEST_CASE(EcdsaSigning)
+{
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/EcdsaSigning/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+  EcdsaKeyParams params;
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  Data data("/TestSecTpmOsx/EcdsaSigning/Data/1");
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DIGEST_ALGORITHM_SHA256));
+
+  shared_ptr<PublicKey> pubkeyPtr;
+  BOOST_CHECK_NO_THROW(pubkeyPtr = tpm.getPublicKeyFromTpm(keyName));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey publicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+      publicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock.value(), sigBlock.value_size(), DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+      bool result = verifier.VerifyMessage(content, sizeof(content),
+                                           buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(result, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+}
 
 BOOST_AUTO_TEST_SUITE_END()
 
diff --git a/tests/unit-tests/security/test-validator.cpp b/tests/unit-tests/security/test-validator.cpp
index b8d6157..bd91280 100644
--- a/tests/unit-tests/security/test-validator.cpp
+++ b/tests/unit-tests/security/test-validator.cpp
@@ -69,6 +69,141 @@
   keyChain.deleteIdentity(identity);
 }
 
+const uint8_t ecdsaSigInfo[] = {
+0x16, 0x1b, // SignatureInfo
+  0x1b, 0x01, // SignatureType
+    0x03,
+  0x1c, 0x16, // KeyLocator
+    0x07, 0x14, // Name
+      0x08, 0x04,
+        0x74, 0x65, 0x73, 0x74,
+      0x08, 0x03,
+        0x6b, 0x65, 0x79,
+      0x08, 0x07,
+        0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72
+};
+
+const uint8_t ecdsaSigValue[] = {
+0x17, 0x40, // SignatureValue
+  0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+  0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+  0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+  0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+  0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b
+};
+
+BOOST_AUTO_TEST_CASE(RsaSignatureVerification)
+{
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
+
+  Name identity("/TestValidator/RsaSignatureVerification");
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+  Name keyName = keyChain.getDefaultKeyNameForIdentity(identity);
+  shared_ptr<PublicKey> publicKey = keyChain.getPublicKey(keyName);
+
+  Name identity2("/TestValidator/RsaSignatureVerification/id2");
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity2));
+  Name keyName2 = keyChain.getDefaultKeyNameForIdentity(identity2);
+  shared_ptr<PublicKey> publicKey2 = keyChain.getPublicKey(keyName2);
+
+
+  Data data("/TestData/1");
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(data, identity));
+  BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey), true);
+  BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey2), false);
+
+  Interest interest("/TestInterest/1");
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(interest, identity));
+  BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey), true);
+  BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey2), false);
+
+  Data wrongData("/TestData/2");
+  Block ecdsaSigInfoBlock(ecdsaSigInfo, sizeof(ecdsaSigInfo));
+  Block ecdsaSigValueBlock(ecdsaSigValue, sizeof(ecdsaSigValue));
+  Signature ecdsaSig(ecdsaSigInfoBlock, ecdsaSigValueBlock);
+  wrongData.setSignature(ecdsaSig);
+  BOOST_CHECK_EQUAL(Validator::verifySignature(wrongData, *publicKey), false);
+
+  keyChain.deleteIdentity(identity);
+  keyChain.deleteIdentity(identity2);
+}
+
+const uint8_t rsaSigInfo[] = {
+0x16, 0x1b, // SignatureInfo
+  0x1b, 0x01, // SignatureType
+    0x01,
+  0x1c, 0x16, // KeyLocator
+    0x07, 0x14, // Name
+      0x08, 0x04,
+        0x74, 0x65, 0x73, 0x74,
+      0x08, 0x03,
+        0x6b, 0x65, 0x79,
+      0x08, 0x07,
+        0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72
+};
+
+const uint8_t rsaSigValue[] = {
+0x17, 0x80, // SignatureValue
+  0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+  0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+  0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+  0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+  0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
+  0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
+  0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
+  0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
+  0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
+  0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
+};
+
+
+BOOST_AUTO_TEST_CASE(EcdsaSignatureVerification)
+{
+  BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+  KeyChain keyChain("sqlite3", "file");
+
+  Name identity("/TestValidator/EcdsaSignatureVerification");
+  EcdsaKeyParams params;
+  // BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity, params));
+  try
+    {
+      keyChain.createIdentity(identity, params);
+    }
+  catch (std::runtime_error& e)
+    {
+      std::cerr << e.what() << std::endl;
+    }
+  Name keyName = keyChain.getDefaultKeyNameForIdentity(identity);
+  shared_ptr<PublicKey> publicKey = keyChain.getPublicKey(keyName);
+
+  Name identity2("/TestValidator/EcdsaSignatureVerification/id2");
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity2, params));
+  Name keyName2 = keyChain.getDefaultKeyNameForIdentity(identity2);
+  shared_ptr<PublicKey> publicKey2 = keyChain.getPublicKey(keyName2);
+
+
+  Data data("/TestData/1");
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(data, identity));
+  BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey), true);
+  BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey2), false);
+
+  Interest interest("/TestInterest/1");
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(interest, identity));
+  BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey), true);
+  BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey2), false);
+
+  Data wrongData("/TestData/2");
+  Block rsaSigInfoBlock(rsaSigInfo, sizeof(rsaSigInfo));
+  Block rsaSigValueBlock(rsaSigValue, sizeof(rsaSigValue));
+  Signature rsaSig(rsaSigInfoBlock, rsaSigValueBlock);
+  wrongData.setSignature(rsaSig);
+  BOOST_CHECK_EQUAL(Validator::verifySignature(wrongData, *publicKey), false);
+
+  keyChain.deleteIdentity(identity);
+  keyChain.deleteIdentity(identity2);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace ndn