security: Enable exporting/importing ECDSA key

Change-Id: I58f722337f26cad4eb6a3c83d883814efc4ed8df
Refs: #1660
diff --git a/tests/unit-tests/security/test-encode-decode-certificate.cpp b/tests/unit-tests/security/test-encode-decode-certificate.cpp
index 2577509..f8cc0fb 100644
--- a/tests/unit-tests/security/test-encode-decode-certificate.cpp
+++ b/tests/unit-tests/security/test-encode-decode-certificate.cpp
@@ -92,7 +92,8 @@
   certificate.setNotAfter(time::fromUnixTimestamp(time::milliseconds(1388100174000LL)));
 
   // subject
-  certificate.addSubjectDescription(CertificateSubjectDescription("2.5.4.41", "TEST NAME"));
+  certificate.addSubjectDescription(CertificateSubjectDescription(oid::ATTRIBUTE_NAME,
+                                                                  "TEST NAME"));
 
   // publicKeyInfo
   ndn::PublicKey key(PUBLIC_KEY, sizeof(PUBLIC_KEY));
@@ -113,7 +114,8 @@
     }
     seq.MessageEnd();
 
-    certificate.addExtension(CertificateExtension("1.3.6.1.5.32.1", true,
+    //create a randome extension
+    certificate.addExtension(CertificateExtension(OID("1.3.6.1.5.32.1"), true,
       reinterpret_cast<const uint8_t*>(extenstionValue.c_str()),
       extenstionValue.size()));
   });
diff --git a/tests/unit-tests/security/test-sec-tpm-file.cpp b/tests/unit-tests/security/test-sec-tpm-file.cpp
index c25a40b..0b900ed 100644
--- a/tests/unit-tests/security/test-sec-tpm-file.cpp
+++ b/tests/unit-tests/security/test-sec-tpm-file.cpp
@@ -289,6 +289,122 @@
   tpm.deleteKeyPairInTpm(keyName);
 }
 
+
+BOOST_AUTO_TEST_CASE(ImportExportEcdsaKey)
+{
+  using namespace CryptoPP;
+
+  std::string imported =
+    "MIGMMEAGCSqGSIb3DQEFDTAzMBsGCSqGSIb3DQEFDDAOBAhqkJiLfzFWtQICCAAw"
+    "FAYIKoZIhvcNAwcECJ1HLtP8OZC6BEgNv9OH2mZdbkxvqTVlRBkUqPbbP3580OG6"
+    "f0htqWSRppcb4IEKYfuPt2qPCYKL2GcAN2pU3eJqhiM7LFTSFaxgBRFozzIwusk=";
+
+  std::string decoded;
+  BOOST_CHECK_NO_THROW(StringSource source(imported,
+                                           true,
+                                           new Base64Decoder(new StringSink(decoded))));
+
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/ImportExportEcdsaKey/ksk-" +
+               boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
+
+  BOOST_REQUIRE_NO_THROW(
+    tpm.importPrivateKeyPkcs5IntoTpm(keyName,
+                                     reinterpret_cast<const uint8_t*>(decoded.c_str()),
+                                     decoded.size(),
+                                     "5678"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), true);
+
+  shared_ptr<PublicKey> publicKey;
+  BOOST_CHECK_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DIGEST_ALGORITHM_SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey ecdsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      ecdsaPublicKey.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(ecdsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content, sizeof(content),
+                                               buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  ConstBufferPtr exported;
+  BOOST_CHECK_NO_THROW(exported = tpm.exportPrivateKeyPkcs5FromTpm(keyName, "1234"));
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs5IntoTpm(keyName, exported->buf(), exported->size(),
+                                                 "1234"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), true);
+
+  const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
+  Block sigBlock2;
+  BOOST_CHECK_NO_THROW(sigBlock2 = tpm.signInTpm(content2, sizeof(content2),
+                                                 keyName, DIGEST_ALGORITHM_SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey ecdsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      ecdsaPublicKey.Load(queue);
+
+      uint8_t buffer[64];
+      size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+                                                  sigBlock2.value(), sigBlock2.value_size(),
+                                                  DSA_DER);
+
+      ECDSA<ECP, SHA256>::Verifier verifier(ecdsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content2, sizeof(content2),
+                                               buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
+}
+
+
 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 3b28c66..a7d1d80 100644
--- a/tests/unit-tests/security/test-sec-tpm-osx.cpp
+++ b/tests/unit-tests/security/test-sec-tpm-osx.cpp
@@ -25,6 +25,7 @@
 #include "util/time.hpp"
 
 #include <boost/lexical_cast.hpp>
+#include <Availability.h>
 
 #include "boost-test.hpp"
 
@@ -177,9 +178,14 @@
     }
 
   tpm.deleteKeyPairInTpm(keyName);
-  // This is some problem related to Mac OS Key chain, and we will fix it later.
-  // BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
-  // BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+  // This is some problem related to Mac OS Key chain.
+  // On OSX 10.8, we cannot delete imported keys, but there is no such problem on OSX 10.9.
+#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_9
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+#endif
+#endif
 }
 
 BOOST_AUTO_TEST_CASE(NonExistingKey)
@@ -246,6 +252,82 @@
   tpm.deleteKeyPairInTpm(keyName);
 }
 
+
+BOOST_AUTO_TEST_CASE(ExportImportEcdsaKey)
+{
+  using namespace CryptoPP;
+
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmOsx/ExportImportEcdsaKey/ksk-" +
+               boost::lexical_cast<std::string>(
+                 time::toUnixTimestamp(time::system_clock::now()).count()));
+
+  EcdsaKeyParams params;
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), true);
+
+  ConstBufferPtr exported;
+  BOOST_CHECK_NO_THROW(exported = tpm.exportPrivateKeyPkcs5FromTpm(keyName, "1234"));
+
+  shared_ptr<PublicKey> publicKey;
+  BOOST_REQUIRE_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs5IntoTpm(keyName,
+                                                 exported->buf(), exported->size(),
+                                                 "1234"));
+
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), true);
+  BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), true);
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock;
+  BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+                                                keyName, DIGEST_ALGORITHM_SHA256));
+
+  try
+    {
+      using namespace CryptoPP;
+
+      ECDSA<ECP, SHA256>::PublicKey ecdsaPublicKey;
+      ByteQueue queue;
+      queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
+      ecdsaPublicKey.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(ecdsaPublicKey);
+      bool isVerified = verifier.VerifyMessage(content, sizeof(content),
+                                               buffer, usedSize);
+
+      BOOST_CHECK_EQUAL(isVerified, true);
+    }
+  catch (CryptoPP::Exception& e)
+    {
+      BOOST_CHECK(false);
+    }
+
+  tpm.deleteKeyPairInTpm(keyName);
+  // This is some problem related to Mac OS Key chain.
+  // On OSX 10.8, we cannot delete imported keys, but there is no such problem on OSX 10.9.
+#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_9
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+#endif
+#endif
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace ndn