security: Add ECDSA signature signing and validation

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