security: Add ECDSA signature signing and validation

Change-Id: I2f193e9d643498a68579ae59a7f524ff446dcb9e
Refs: #1660
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());