security: add vectored API for verify and sign

Add vectored input for BufferSource transform

refs #4804

Change-Id: I4949afe5ddb5a49ce6a956da6bc7931cf3719021
diff --git a/tests/unit/security/tpm/back-end.t.cpp b/tests/unit/security/tpm/back-end.t.cpp
index 8d4b41a..8abc745 100644
--- a/tests/unit/security/tpm/back-end.t.cpp
+++ b/tests/unit/security/tpm/back-end.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -117,23 +117,40 @@
   unique_ptr<KeyHandle> key = tpm.createKey(identity, RsaKeyParams());
   Name keyName = key->getKeyName();
 
-  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
-  auto sigValue = key->sign(DigestAlgorithm::SHA256, content, sizeof(content));
-  BOOST_REQUIRE(sigValue != nullptr);
-  Block sigBlock(tlv::SignatureValue, sigValue);
-
   transform::PublicKey pubKey;
   ConstBufferPtr pubKeyBits = key->derivePublicKey();
   pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
 
-  bool result;
+  // Sign using single buffer API
+  const uint8_t content1[] = {0x01, 0x02, 0x03, 0x04};
+  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, content1, sizeof(content1));
+  BOOST_REQUIRE(sigValueSingle != nullptr);
+
+  bool resultSingle;
   {
     using namespace transform;
-    bufferSource(content, sizeof(content)) >>
-      verifierFilter(DigestAlgorithm::SHA256, pubKey, sigBlock.value(), sigBlock.value_size()) >>
-      boolSink(result);
+    bufferSource(content1, sizeof(content1)) >>
+      verifierFilter(DigestAlgorithm::SHA256, pubKey,
+                     sigValueSingle->data(), sigValueSingle->size()) >>
+      boolSink(resultSingle);
   }
-  BOOST_CHECK_EQUAL(result, true);
+  BOOST_CHECK_EQUAL(resultSingle, true);
+
+  // Sign using vectored API
+  const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
+  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {{content1, sizeof(content1)},
+                                                            {content2, sizeof(content2)}});
+  BOOST_REQUIRE(sigValueVector != nullptr);
+
+  bool resultVector;
+  {
+    using namespace transform;
+    bufferSource({{content1, sizeof(content1)}, {content2, sizeof(content2)}}) >>
+      verifierFilter(DigestAlgorithm::SHA256, pubKey,
+                     sigValueVector->data(), sigValueVector->size()) >>
+      boolSink(resultVector);
+  }
+  BOOST_CHECK_EQUAL(resultVector, true);
 
   tpm.deleteKey(keyName);
   BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
@@ -175,23 +192,40 @@
   unique_ptr<KeyHandle> key = tpm.createKey(identity, EcKeyParams());
   Name ecKeyName = key->getKeyName();
 
-  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
-  auto sigValue = key->sign(DigestAlgorithm::SHA256, content, sizeof(content));
-  BOOST_REQUIRE(sigValue != nullptr);
-  Block sigBlock(tlv::SignatureValue, sigValue);
-
   transform::PublicKey pubKey;
   ConstBufferPtr pubKeyBits = key->derivePublicKey();
   pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
 
-  bool result;
+  // Sign using single buffer API
+  const uint8_t content1[] = {0x01, 0x02, 0x03, 0x04};
+  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, content1, sizeof(content1));
+  BOOST_REQUIRE(sigValueSingle != nullptr);
+
+  bool resultSingle;
   {
     using namespace transform;
-    bufferSource(content, sizeof(content)) >>
-      verifierFilter(DigestAlgorithm::SHA256, pubKey, sigBlock.value(), sigBlock.value_size()) >>
-      boolSink(result);
+    bufferSource(content1, sizeof(content1)) >>
+      verifierFilter(DigestAlgorithm::SHA256, pubKey,
+                     sigValueSingle->data(), sigValueSingle->size()) >>
+      boolSink(resultSingle);
   }
-  BOOST_CHECK_EQUAL(result, true);
+  BOOST_CHECK_EQUAL(resultSingle, true);
+
+  // Sign using vectored API
+  const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
+  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {{content1, sizeof(content1)},
+                                                            {content2, sizeof(content2)}});
+  BOOST_REQUIRE(sigValueVector != nullptr);
+
+  bool resultVector;
+  {
+    using namespace transform;
+    bufferSource({{content1, sizeof(content1)}, {content2, sizeof(content2)}}) >>
+      verifierFilter(DigestAlgorithm::SHA256, pubKey,
+                     sigValueVector->data(), sigValueVector->size()) >>
+      boolSink(resultVector);
+  }
+  BOOST_CHECK_EQUAL(resultVector, true);
 
   tpm.deleteKey(ecKeyName);
   BOOST_CHECK_EQUAL(tpm.hasKey(ecKeyName), false);
@@ -207,14 +241,24 @@
   unique_ptr<KeyHandle> key = tpm.createKey(identity, HmacKeyParams());
   Name hmacKeyName = key->getKeyName();
 
-  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
-  auto sigValue = key->sign(DigestAlgorithm::SHA256, content, sizeof(content));
-  BOOST_REQUIRE(sigValue != nullptr);
-  Block sigBlock(tlv::SignatureValue, sigValue);
+  // Sign and verify using single buffer API
+  const uint8_t content1[] = {0x01, 0x02, 0x03, 0x04};
+  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, content1, sizeof(content1));
+  BOOST_REQUIRE(sigValueSingle != nullptr);
+  bool resultSingle = key->verify(DigestAlgorithm::SHA256, content1, sizeof(content1),
+                                  sigValueSingle->data(), sigValueSingle->size());
+  BOOST_CHECK_EQUAL(resultSingle, true);
 
-  bool result = key->verify(DigestAlgorithm::SHA256, content, sizeof(content),
-                            sigBlock.value(), sigBlock.value_size());
-  BOOST_CHECK_EQUAL(result, true);
+  // Sign and verify using vectored API
+  const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
+  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {{content1, sizeof(content1)},
+                                                            {content2, sizeof(content2)}});
+  BOOST_REQUIRE(sigValueVector != nullptr);
+  bool resultVector = key->verify(DigestAlgorithm::SHA256,
+                                  {{content1, sizeof(content1)},
+                                   {content2, sizeof(content2)}},
+                                  sigValueVector->data(), sigValueVector->size());
+  BOOST_CHECK_EQUAL(resultVector, true);
 
   tpm.deleteKey(hmacKeyName);
   BOOST_CHECK_EQUAL(tpm.hasKey(hmacKeyName), false);
diff --git a/tests/unit/security/transform/buffer-source.t.cpp b/tests/unit/security/transform/buffer-source.t.cpp
index 80b9d8d..8f1a23e 100644
--- a/tests/unit/security/transform/buffer-source.t.cpp
+++ b/tests/unit/security/transform/buffer-source.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -43,7 +43,7 @@
   std::ostringstream os1;
   bufferSource(in, sizeof(in)) >> streamSink(os1);
   std::string out1 = os1.str();
-  BOOST_CHECK_EQUAL_COLLECTIONS(in, in + sizeof(in), out1.begin(), out1.end());
+  BOOST_CHECK_EQUAL_COLLECTIONS(out1.begin(), out1.end(), in, in + sizeof(in));
 
   std::string in2 =
     "0123456701234567012345670123456701234567012345670123456701234567"
@@ -70,13 +70,23 @@
   std::ostringstream os2;
   bufferSource(in2) >> streamSink(os2);
   std::string out2 = os2.str();
-  BOOST_CHECK_EQUAL_COLLECTIONS(in2.begin(), in2.end(), out2.begin(), out2.end());
+  BOOST_CHECK_EQUAL_COLLECTIONS(out2.begin(), out2.end(), in2.begin(), in2.end());
 
   Buffer in3(in, sizeof(in));
   std::ostringstream os3;
   bufferSource(in3) >> streamSink(os3);
   std::string out3 = os3.str();
-  BOOST_CHECK_EQUAL_COLLECTIONS(in3.begin(), in3.end(), out3.begin(), out3.end());
+  BOOST_CHECK_EQUAL_COLLECTIONS(out3.begin(), out3.end(), in3.begin(), in3.end());
+
+  InputBuffers in4{{in, sizeof(in)}, {reinterpret_cast<const uint8_t*>(in2.data()), in2.size()}};
+  std::ostringstream os4;
+  bufferSource(in4) >> streamSink(os4);
+  std::string out4 = os4.str();
+  BOOST_CHECK_EQUAL(out4.size(), sizeof(in) + in2.size());
+  BOOST_CHECK_EQUAL_COLLECTIONS(out4.begin(), out4.begin() + in4[0].second,
+                                in4[0].first, in4[0].first + in4[0].second);
+  BOOST_CHECK_EQUAL_COLLECTIONS(out4.begin() + in4[0].second, out4.end(),
+                                in4[1].first, in4[1].first + in4[1].second);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestBufferSource