util: backport C++20 std::span and use it in various APIs

Implementation taken from span-lite by Martin Moene,
commit 337af6e23f6d3264136c16565546244da23159ba

Change-Id: Icfd0ba6841cbf6ef7870c31c881df940da9faf7e
diff --git a/tests/unit/security/transform/private-key.t.cpp b/tests/unit/security/transform/private-key.t.cpp
index 042f571..87d39fe 100644
--- a/tests/unit/security/transform/private-key.t.cpp
+++ b/tests/unit/security/transform/private-key.t.cpp
@@ -56,8 +56,7 @@
   BOOST_CHECK_EQUAL(sKey.getKeySize(), 0);
   BOOST_CHECK_THROW(sKey.getKeyDigest(DigestAlgorithm::SHA256), PrivateKey::Error);
   BOOST_CHECK_THROW(sKey.derivePublicKey(), PrivateKey::Error);
-  const uint8_t theAnswer = 42;
-  BOOST_CHECK_THROW(sKey.decrypt(&theAnswer, sizeof(theAnswer)), PrivateKey::Error);
+  BOOST_CHECK_THROW(sKey.decrypt({}), PrivateKey::Error);
   std::ostringstream os;
   BOOST_CHECK_THROW(sKey.savePkcs1(os), PrivateKey::Error);
   std::string passwd("password");
@@ -69,7 +68,7 @@
 {
   const Buffer buf(16);
   PrivateKey sKey;
-  sKey.loadRaw(KeyType::HMAC, buf.data(), buf.size());
+  sKey.loadRaw(KeyType::HMAC, buf);
   auto digest = sKey.getKeyDigest(DigestAlgorithm::SHA256);
 
   const uint8_t expected[] = {
@@ -85,17 +84,17 @@
 {
   const Buffer buf(32);
   PrivateKey sKey;
-  sKey.loadRaw(KeyType::HMAC, buf.data(), buf.size());
+  sKey.loadRaw(KeyType::HMAC, buf);
 #if OPENSSL_VERSION_NUMBER < 0x30000000L // FIXME #5154
   BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::HMAC);
   BOOST_CHECK_EQUAL(sKey.getKeySize(), 256);
 #endif
 
   PrivateKey sKey2;
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::NONE, buf.data(), buf.size()), std::invalid_argument);
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::RSA, buf.data(), buf.size()), std::invalid_argument);
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::EC, buf.data(), buf.size()), std::invalid_argument);
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::AES, buf.data(), buf.size()), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::NONE, buf), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::RSA, buf), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::EC, buf), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::AES, buf), std::invalid_argument);
 }
 
 struct RsaKey_DesEncrypted
@@ -397,7 +396,7 @@
                    const ConstBufferPtr& pkcs1)
 {
   PrivateKey sKey;
-  sKey.loadPkcs8(encoding->data(), encoding->size(), password.data(), password.size());
+  sKey.loadPkcs8(*encoding, password.data(), password.size());
   OBufferStream os;
   sKey.savePkcs1(os);
   BOOST_CHECK_EQUAL_COLLECTIONS(pkcs1->begin(), pkcs1->end(),
@@ -418,17 +417,15 @@
 {
   T dataSet;
 
-  auto sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data());
-  auto sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
+  auto sKeyPkcs1Base64 = make_span(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                                   dataSet.privateKeyPkcs1.size());
   OBufferStream os;
-  bufferSource(sKeyPkcs1Base64, sKeyPkcs1Base64Len) >> base64Decode() >> streamSink(os);
-  ConstBufferPtr sKeyPkcs1Buf = os.buf();
-  const uint8_t* sKeyPkcs1 = sKeyPkcs1Buf->data();
-  size_t sKeyPkcs1Len = sKeyPkcs1Buf->size();
+  bufferSource(sKeyPkcs1Base64) >> base64Decode() >> streamSink(os);
+  auto sKeyPkcs1 = os.buf();
 
   // load key in base64-encoded pkcs1 format
   PrivateKey sKey;
-  BOOST_CHECK_NO_THROW(sKey.loadPkcs1Base64(sKeyPkcs1Base64, sKeyPkcs1Base64Len));
+  BOOST_CHECK_NO_THROW(sKey.loadPkcs1Base64(sKeyPkcs1Base64));
   BOOST_CHECK_EQUAL(sKey.getKeySize(), dataSet.keySize);
 
   std::stringstream ss2(dataSet.privateKeyPkcs1);
@@ -437,32 +434,31 @@
 
   // load key in pkcs1 format
   PrivateKey sKey3;
-  BOOST_CHECK_NO_THROW(sKey3.loadPkcs1(sKeyPkcs1, sKeyPkcs1Len));
+  BOOST_CHECK_NO_THROW(sKey3.loadPkcs1(*sKeyPkcs1));
   BOOST_CHECK_EQUAL(sKey3.getKeySize(), dataSet.keySize);
 
   std::stringstream ss4;
-  ss4.write(reinterpret_cast<const char*>(sKeyPkcs1), sKeyPkcs1Len);
+  ss4.write(reinterpret_cast<const char*>(sKeyPkcs1->data()), sKeyPkcs1->size());
   PrivateKey sKey4;
   BOOST_CHECK_NO_THROW(sKey4.loadPkcs1(ss4));
 
   // save key in base64-encoded pkcs1 format
   OBufferStream os2;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs1Base64(os2));
-  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1Base64, sKeyPkcs1Base64 + sKeyPkcs1Base64Len,
+  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1Base64.begin(), sKeyPkcs1Base64.end(),
                                 os2.buf()->begin(), os2.buf()->end());
 
   // save key in pkcs1 format
   OBufferStream os3;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs1(os3));
-  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1, sKeyPkcs1 + sKeyPkcs1Len,
+  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1->begin(), sKeyPkcs1->end(),
                                 os3.buf()->begin(), os3.buf()->end());
 
-  auto sKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs8.data());
-  auto sKeyPkcs8Base64Len = dataSet.privateKeyPkcs8.size();
+  auto sKeyPkcs8Base64 = make_span(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs8.data()),
+                                   dataSet.privateKeyPkcs8.size());
   OBufferStream os4;
-  bufferSource(sKeyPkcs8Base64, sKeyPkcs8Base64Len) >> base64Decode() >> streamSink(os4);
-  const uint8_t* sKeyPkcs8 = os4.buf()->data();
-  size_t sKeyPkcs8Len = os4.buf()->size();
+  bufferSource(sKeyPkcs8Base64) >> base64Decode() >> streamSink(os4);
+  auto sKeyPkcs8 = os4.buf();
 
   std::string password("password");
   std::string wrongpw("wrongpw");
@@ -474,12 +470,11 @@
 
   // load key in base64-encoded pkcs8 format
   PrivateKey sKey5;
-  BOOST_CHECK_NO_THROW(sKey5.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len,
-                                             password.data(), password.size()));
+  BOOST_CHECK_NO_THROW(sKey5.loadPkcs8Base64(sKeyPkcs8Base64, password.data(), password.size()));
   BOOST_CHECK_EQUAL(sKey5.getKeySize(), dataSet.keySize);
 
   PrivateKey sKey6;
-  BOOST_CHECK_NO_THROW(sKey6.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, pwCallback));
+  BOOST_CHECK_NO_THROW(sKey6.loadPkcs8Base64(sKeyPkcs8Base64, pwCallback));
 
   std::stringstream ss7(dataSet.privateKeyPkcs8);
   PrivateKey sKey7;
@@ -491,25 +486,25 @@
 
   // load key in pkcs8 format
   PrivateKey sKey9;
-  BOOST_CHECK_NO_THROW(sKey9.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, password.data(), password.size()));
+  BOOST_CHECK_NO_THROW(sKey9.loadPkcs8(*sKeyPkcs8, password.data(), password.size()));
   BOOST_CHECK_EQUAL(sKey9.getKeySize(), dataSet.keySize);
 
   PrivateKey sKey10;
-  BOOST_CHECK_NO_THROW(sKey10.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, pwCallback));
+  BOOST_CHECK_NO_THROW(sKey10.loadPkcs8(*sKeyPkcs8, pwCallback));
 
   std::stringstream ss11;
-  ss11.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
+  ss11.write(reinterpret_cast<const char*>(sKeyPkcs8->data()), sKeyPkcs8->size());
   PrivateKey sKey11;
   BOOST_CHECK_NO_THROW(sKey11.loadPkcs8(ss11, password.data(), password.size()));
 
   std::stringstream ss12;
-  ss12.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
+  ss12.write(reinterpret_cast<const char*>(sKeyPkcs8->data()), sKeyPkcs8->size());
   PrivateKey sKey12;
   BOOST_CHECK_NO_THROW(sKey12.loadPkcs8(ss12, pwCallback));
 
   // load key using wrong password, Error is expected
   PrivateKey sKey13;
-  BOOST_CHECK_THROW(sKey13.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, wrongpw.data(), wrongpw.size()),
+  BOOST_CHECK_THROW(sKey13.loadPkcs8Base64(sKeyPkcs8Base64, wrongpw.data(), wrongpw.size()),
                     PrivateKey::Error);
   BOOST_CHECK_EQUAL(sKey13.getKeyType(), KeyType::NONE);
   BOOST_CHECK_EQUAL(sKey13.getKeySize(), 0);
@@ -517,30 +512,30 @@
   // save key in base64-encoded pkcs8 format
   OBufferStream os14;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os14, password.data(), password.size()));
-  checkPkcs8Base64Encoding(os14.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Base64Encoding(os14.buf(), password, sKeyPkcs1);
 
   OBufferStream os15;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os15, pwCallback));
-  checkPkcs8Base64Encoding(os15.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Base64Encoding(os15.buf(), password, sKeyPkcs1);
 
   // save key in pkcs8 format
   OBufferStream os16;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os16, password.data(), password.size()));
-  checkPkcs8Encoding(os16.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Encoding(os16.buf(), password, sKeyPkcs1);
 
   OBufferStream os17;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os17, pwCallback));
-  checkPkcs8Encoding(os17.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Encoding(os17.buf(), password, sKeyPkcs1);
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(DerivePublicKey, T, KeyTestDataSets)
 {
   T dataSet;
 
-  auto sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data());
-  auto sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
+  auto sKeyPkcs1Base64 = make_span(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                                   dataSet.privateKeyPkcs1.size());
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(sKeyPkcs1Base64, sKeyPkcs1Base64Len);
+  sKey.loadPkcs1Base64(sKeyPkcs1Base64);
 
   // derive public key and compare
   ConstBufferPtr pKeyBits = sKey.derivePublicKey();
@@ -555,8 +550,8 @@
   RsaKey_Aes256Encrypted dataSet;
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
-                       dataSet.privateKeyPkcs1.size());
+  sKey.loadPkcs1Base64({reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                        dataSet.privateKeyPkcs1.size()});
   BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
 
   const uint8_t plaintext[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
@@ -573,7 +568,7 @@
   OBufferStream os;
   bufferSource(ciphertext) >> base64Decode() >> streamSink(os);
 
-  auto decrypted = sKey.decrypt(os.buf()->data(), os.buf()->size());
+  auto decrypted = sKey.decrypt(*os.buf());
   BOOST_CHECK_EQUAL_COLLECTIONS(plaintext, plaintext + sizeof(plaintext),
                                 decrypted->begin(), decrypted->end());
 }
@@ -583,19 +578,19 @@
   RsaKey_Aes256Encrypted dataSet;
 
   PublicKey pKey;
-  pKey.loadPkcs8Base64(reinterpret_cast<const uint8_t*>(dataSet.publicKey.data()),
-                       dataSet.publicKey.size());
+  pKey.loadPkcs8Base64({reinterpret_cast<const uint8_t*>(dataSet.publicKey.data()),
+                        dataSet.publicKey.size()});
   BOOST_CHECK_EQUAL(pKey.getKeyType(), KeyType::RSA);
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
-                       dataSet.privateKeyPkcs1.size());
+  sKey.loadPkcs1Base64({reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                        dataSet.privateKeyPkcs1.size()});
   BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
 
   const uint8_t plaintext[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
 
-  auto ciphertext = pKey.encrypt(plaintext, sizeof(plaintext));
-  auto decrypted = sKey.decrypt(ciphertext->data(), ciphertext->size());
+  auto ciphertext = pKey.encrypt(plaintext);
+  auto decrypted = sKey.decrypt(*ciphertext);
   BOOST_CHECK_EQUAL_COLLECTIONS(plaintext, plaintext + sizeof(plaintext),
                                 decrypted->begin(), decrypted->end());
 }
@@ -606,10 +601,10 @@
   bufferSource("Y2lhbyFob2xhIWhlbGxvIQ==") >> base64Decode() >> streamSink(os);
 
   auto ecKey = generatePrivateKey(EcKeyParams());
-  BOOST_CHECK_THROW(ecKey->decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
+  BOOST_CHECK_THROW(ecKey->decrypt(*os.buf()), PrivateKey::Error);
 
   auto hmacKey = generatePrivateKey(HmacKeyParams());
-  BOOST_CHECK_THROW(hmacKey->decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
+  BOOST_CHECK_THROW(hmacKey->decrypt(*os.buf()), PrivateKey::Error);
 }
 
 class RsaKeyGenParams
@@ -673,7 +668,7 @@
 
   const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
   OBufferStream os;
-  BOOST_REQUIRE_NO_THROW(bufferSource(data, sizeof(data)) >>
+  BOOST_REQUIRE_NO_THROW(bufferSource(data) >>
                          signerFilter(DigestAlgorithm::SHA256, *sKey) >>
                          streamSink(os));
   auto sig = os.buf();
@@ -684,8 +679,8 @@
     BOOST_REQUIRE(pKeyBits != nullptr);
     T::checkPublicKey(*pKeyBits);
     PublicKey pKey;
-    pKey.loadPkcs8(pKeyBits->data(), pKeyBits->size());
-    BOOST_CHECK_NO_THROW(bufferSource(data, sizeof(data)) >>
+    pKey.loadPkcs8(*pKeyBits);
+    BOOST_CHECK_NO_THROW(bufferSource(data) >>
                          verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
                          boolSink(result));
   }
@@ -693,7 +688,7 @@
 #if OPENSSL_VERSION_NUMBER >= 0x1010100fL
     BOOST_CHECK_THROW(sKey->derivePublicKey(), PrivateKey::Error);
 #endif
-    BOOST_CHECK_NO_THROW(bufferSource(data, sizeof(data)) >>
+    BOOST_CHECK_NO_THROW(bufferSource(data) >>
                          verifierFilter(DigestAlgorithm::SHA256, *sKey, sig->data(), sig->size()) >>
                          boolSink(result));
   }