security: Reorganizing source code to prepare for support of two version of NDN certificates

This commit also removes unused ndn_digestSha256 function and deprecates
crypto::sha256 in favor of crypto::computeSha256Digest in util/crypto.hpp.

Change-Id: I24ee50ff073a96b868633bdf2cfade412d3605f3
Refs: #3098
diff --git a/src/security/v1/certificate.cpp b/src/security/v1/certificate.cpp
new file mode 100644
index 0000000..823c994
--- /dev/null
+++ b/src/security/v1/certificate.cpp
@@ -0,0 +1,359 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#include "certificate.hpp"
+#include "../../util/time.hpp"
+#include "cryptopp.hpp"
+#include "../../encoding/cryptopp/asn_ext.hpp"
+#include "../../encoding/buffer-stream.hpp"
+#include "../../util/concepts.hpp"
+#include "../../util/indented-stream.hpp"
+
+#include <boost/algorithm/string/split.hpp>
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+BOOST_CONCEPT_ASSERT((WireEncodable<Certificate>));
+BOOST_CONCEPT_ASSERT((WireDecodable<Certificate>));
+static_assert(std::is_base_of<tlv::Error, Certificate::Error>::value,
+              "Certificate::Error must inherit from tlv::Error");
+
+Certificate::Certificate()
+  : m_notBefore(time::system_clock::TimePoint::max())
+  , m_notAfter(time::system_clock::TimePoint::min())
+{
+}
+
+Certificate::Certificate(const Data& data)
+  // Use the copy constructor.  It clones the signature object.
+  : Data(data)
+{
+  decode();
+}
+
+Certificate::Certificate(const Block& block)
+  : Data(block)
+{
+  decode();
+}
+
+Certificate::~Certificate()
+{
+}
+
+void
+Certificate::wireDecode(const Block& wire)
+{
+  Data::wireDecode(wire);
+  decode();
+}
+
+bool
+Certificate::isTooEarly()
+{
+  if (time::system_clock::now() < m_notBefore)
+    return true;
+  else
+    return false;
+}
+
+bool
+Certificate::isTooLate()
+{
+  if (time::system_clock::now() > m_notAfter)
+    return true;
+  else
+    return false;
+}
+
+void
+Certificate::encode()
+{
+  // Name
+  //    <key_name>/ID-CERT/<id#>
+  // Content
+  // DER encoded idCert:
+  //
+  //    idCert ::= SEQUENCE {
+  //        validity            Validity,
+  //        subject             Name,
+  //        subjectPubKeyInfo   SubjectPublicKeyInfo,
+  //        extension           Extensions OPTIONAL   }
+  //
+  //    Validity ::= SEQUENCE {
+  //        notBefore           Time,
+  //        notAfter            Time   }
+  //
+  //    Name ::= CHOICE {
+  //        RDNSequence   }
+  //
+  //    RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+  //
+  //    RelativeDistinguishedName ::=
+  //        SET OF AttributeTypeAndValue
+  //
+  //    SubjectPublicKeyInfo ::= SEQUENCE {
+  //        algorithm           AlgorithmIdentifier
+  //        keybits             BIT STRING   }
+  //
+  //    Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+  //
+  // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
+  //
+  // KeyLocator
+  //    issuer’s certificate name
+  // Signature
+
+  using namespace CryptoPP;
+
+  OBufferStream os;
+  CryptoPP::FileSink sink(os);
+
+  // idCert ::= SEQUENCE {
+  //     validity            Validity,
+  //     subject             Name,
+  //     subjectPubKeyInfo   SubjectPublicKeyInfo,
+  //     extension           Extensions OPTIONAL   }
+  DERSequenceEncoder idCert(sink);
+  {
+    // Validity ::= SEQUENCE {
+    //       notBefore           Time,
+    //       notAfter            Time   }
+    DERSequenceEncoder validity(idCert);
+    {
+      DEREncodeGeneralTime(validity, m_notBefore);
+      DEREncodeGeneralTime(validity, m_notAfter);
+    }
+    validity.MessageEnd();
+
+    // Name ::= CHOICE {
+    //     RDNSequence   }
+    //
+    // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+    DERSequenceEncoder name(idCert);
+    {
+      for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin();
+           it != m_subjectDescriptionList.end(); ++it)
+        {
+          it->encode(name);
+        }
+    }
+    name.MessageEnd();
+
+    // SubjectPublicKeyInfo
+    m_key.encode(idCert);
+
+    // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+    //
+    // Extension ::= SEQUENCE {
+    //        extnID      OBJECT IDENTIFIER,
+    //        critical    BOOLEAN DEFAULT FALSE,
+    //        extnValue   OCTET STRING  }
+    if (!m_extensionList.empty())
+      {
+        DERSequenceEncoder extensions(idCert);
+        {
+          for (ExtensionList::iterator it = m_extensionList.begin();
+               it != m_extensionList.end(); ++it)
+            {
+              it->encode(extensions);
+            }
+        }
+        extensions.MessageEnd();
+      }
+  }
+
+  idCert.MessageEnd();
+
+  setContent(os.buf());
+  setContentType(tlv::ContentType_Key);
+}
+
+void
+Certificate::decode()
+{
+  using namespace CryptoPP;
+
+  try {
+    OBufferStream os;
+    StringSource source(getContent().value(), getContent().value_size(), true);
+
+    // idCert ::= SEQUENCE {
+    //     validity            Validity,
+    //     subject             Name,
+    //     subjectPubKeyInfo   SubjectPublicKeyInfo,
+    //     extension           Extensions OPTIONAL   }
+    BERSequenceDecoder idCert(source);
+    {
+      // Validity ::= SEQUENCE {
+      //       notBefore           Time,
+      //       notAfter            Time   }
+      BERSequenceDecoder validity(idCert);
+      {
+        BERDecodeTime(validity, m_notBefore);
+        BERDecodeTime(validity, m_notAfter);
+      }
+      validity.MessageEnd();
+
+      // Name ::= CHOICE {
+      //     RDNSequence   }
+      //
+      // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+      m_subjectDescriptionList.clear();
+      BERSequenceDecoder name(idCert);
+      {
+        while (!name.EndReached())
+          {
+            m_subjectDescriptionList.push_back(CertificateSubjectDescription(name));
+          }
+      }
+      name.MessageEnd();
+
+      // SubjectPublicKeyInfo ::= SEQUENCE {
+      //     algorithm           AlgorithmIdentifier
+      //     keybits             BIT STRING   }
+      m_key.decode(idCert);
+
+      // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+      //
+      // Extension ::= SEQUENCE {
+      //        extnID      OBJECT IDENTIFIER,
+      //        critical    BOOLEAN DEFAULT FALSE,
+      //        extnValue   OCTET STRING  }
+      m_extensionList.clear();
+      if (!idCert.EndReached())
+        {
+          BERSequenceDecoder extensions(idCert);
+          {
+            while (!extensions.EndReached())
+              {
+                m_extensionList.push_back(CertificateExtension(extensions));
+              }
+          }
+          extensions.MessageEnd();
+        }
+    }
+
+    idCert.MessageEnd();
+  }
+  catch (CryptoPP::BERDecodeErr&) {
+    BOOST_THROW_EXCEPTION(Error("Certificate Decoding Error"));
+  }
+}
+
+void
+Certificate::printCertificate(std::ostream& oss, const std::string& indent) const
+{
+  util::IndentedStream os(oss, indent);
+
+  os << "Certificate name:\n";
+  os << "  " << getName() << "\n";
+  os << "Validity:\n";
+  {
+    os << "  NotBefore: " << time::toIsoString(m_notBefore) << "\n";
+    os << "  NotAfter: "  << time::toIsoString(m_notAfter)  << "\n";
+  }
+
+  os << "Subject Description:\n";
+  for (const auto& description : m_subjectDescriptionList)
+    os << "  " << description.getOidString() << ": " << description.getValue() << "\n";
+
+  os << "Public key bits: ";
+  switch (m_key.getKeyType()) {
+  case KeyType::RSA:
+    os << "(RSA)";
+    break;
+  case KeyType::EC:
+    os << "(ECDSA)";
+    break;
+  default:
+    os << "(Unknown key type)";
+    break;
+  }
+  os << "\n";
+
+  {
+    util::IndentedStream os2(os, "  ");
+    CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os2), true, 64);
+    m_key.encode(encoder);
+  }
+
+  os << "Signature Information:\n";
+  {
+    os << "  Signature Type: ";
+    switch (getSignature().getType()) {
+    case tlv::SignatureTypeValue::DigestSha256:
+      os << "DigestSha256";
+      break;
+    case tlv::SignatureTypeValue::SignatureSha256WithRsa:
+      os << "SignatureSha256WithRsa";
+      break;
+    case tlv::SignatureTypeValue::SignatureSha256WithEcdsa:
+      os << "SignatureSha256WithEcdsa";
+      break;
+    default:
+      os << "Unknown Signature Type";
+    }
+    os << "\n";
+
+    if (getSignature().hasKeyLocator()) {
+      const KeyLocator& keyLocator = getSignature().getKeyLocator();
+      os << "  Key Locator: ";
+      switch (keyLocator.getType()) {
+      case KeyLocator::KeyLocator_Name:
+        {
+          const Name& signerName = keyLocator.getName();
+          if (signerName.isPrefixOf(getName()))
+            os << "(Self-Signed) " << keyLocator.getName();
+          else
+            os << "(Name) " << keyLocator.getName();
+          break;
+        }
+      case KeyLocator::KeyLocator_KeyDigest:
+        os << "(KeyDigest)";
+        break;
+      case KeyLocator::KeyLocator_None:
+        os << "None";
+        break;
+      default:
+        os << "Unknown";
+      }
+      os << "\n";
+    }
+  }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Certificate& cert)
+{
+  cert.printCertificate(os);
+  return os;
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn