docs: Update of tutorials and other minor fixes

Change-Id: I87d8679d38b3f17f8d4d8dbad3d5f01b3cc4ce7b
diff --git a/docs/tutorials/security-library.rst b/docs/tutorials/security-library.rst
index dfb1419..4f88f72 100644
--- a/docs/tutorials/security-library.rst
+++ b/docs/tutorials/security-library.rst
@@ -1,115 +1,141 @@
 Security Library Tutorial
 =========================
 
-Key Management
---------------
+.. contents::
 
 Identity, Key and Certificates
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------
 
-All keys, certificates and their corresponding identities are managed by
-KeyChain.
+All keys, certificates and their corresponding identities are managed by :ndn-cxx:`KeyChain`.
 
-Before signing a packet, you need to assure that the signing key and its
-corresponding identity certificate exist in the KeyChain. The private
-part of the signing key is used to generate signature, while the
-identity certificate is used to constructed the KeyLocator.
+An real world **identity** can be expressed by a namespace.  (e.g.,
+``/ndn/edu/ucla/alice``, or ``/ndn/edu/ucla/BoelterHall/4805``).
 
-In KeyChain, keys and certificates are managed in terms of identities
-which are expressed by namespaces (e.g., ``/ndn/edu/ucla/irl/yingdi``, or
-``/ndn/edu/ucla/boelter\_hall/room\_4805``). Each pair of keys belongs to
-only one identity, and it is named by the identity name appended with a
-key ID (e.g., ``/ndn/edu/ucla/irl/yingdi/ksk-1234567890``, or
-``/ndn/edu/ucla/boelter\_hall/room\_4805/ksk-1357924680``). However, one
-identity may have more than one pair of keys, but only one of them is
-the **default key** of the identity. A key pair without any identity
-certificates is not quite useful. A key pair may have more than one
-identity certificates, but only one of them is the **default
-certificate**. Therefore, for a given identity, there is at only one
-default identity certificate, which is the default certificates of its
-default key.
+**Keys** belonging to an identity are named under the identity's namespace, with a unique
+**KeyId**::
 
-While keys and certificates can be created offline using NDN security
-tools **ndnsec**, they can be created online using the KeyChain API. The
-simplest way is to call ``KeyChain::createIdentity``.
+    /<identity_name>/[KeyId]
+
+For now, only two types of KeyId are specified: ``ksk-[timestamp]`` and
+``dsk-[timestamp]``.  The first type of KeyId is used to denote Key-Signing-Key (KSK)
+which is supposed to have a long lifetime.  The second type of KeyId is used to denote
+Data-Signing-Key (DSK) which is supposed to have a short lifetime.  Both types of KeyId
+use timestamps (number of milliseconds since unix epoch) to provide relative uniqueness of
+key names.  Replacing timestamp with key hash can bring stronger uniqueness but on the
+cost of longer name.  Therefore, key hash is not used for now.  For example,
+``/ndn/edu/ucla/alice/ksk-1234567890`` or
+``/ndn/edu/ucla/BoelterHall/4805/dsk-1357924680``.
+
+An identity may have more than one keys associated with it.  For example, one may have a
+KSK to sign other keys and a DSK to sign data packets, or one may periodically replace its
+expired DSK/KSK with a new key.
+
+The private part of a key ("private key"), is stored in a :ndn-cxx:`Trusted Platform
+Module (TPM) <SecTpm>`.  The public part ("public key"), is managed in a
+:ndn-cxx:`Public-key Information Base (PIB) <SecPublicInfo>`.  The most important
+information managed by PIB is **certificates** of public keys.  A certificate binds a
+public key to its key name or the corresponding identity.  The signer (or issuer) of a
+certificate vouches for the binding through its own signature.  With different signers
+vouching for the binding, a public key may have more than one certificates.
+
+The certificate name follows the naming convention of `NDNS (NDN Domain Name Service) <http://lasr.cs.ucla.edu/afanasyev/data/files/Afanasyev/afanasyev-phd-thesis.pdf>`_.  The
+public key name will be broken into two parts:
+
+- The first part ("authoritative namespace") will be put before a name component ``KEY``
+  which serves as an application tag
+- The second part ("label") will be put between ``KEY`` and ``ID-CERT`` which serves as an
+  indicator of certificate.
+
+A version number of the certificate is appended after ``ID-CERT``.  For example,
+``/ndn/edu/ucla/KEY/alice/ksk-1234567890/ID-CERT/%FD%01`` or
+``/ndn/edu/ucla/BoelterHall/4805/KEY/dsk-1357924680/ID-CERT/%FD%44``.
+
+The :ndn-cxx:`NDN certificate <IdentityCertificate>` is just an ordinary `NDN-TLV Data
+packet <http://named-data.net/doc/ndn-tlv/data.html>`_, with the content part in DER
+encoding that resembles X.509 certificate:
+
+.. code-block:: cpp
+
+    // NDN-TLV Encoding
+    Certificate ::= DATA-TLV TLV-LENGTH
+                      Name
+                      MetaInfo (= CertificateMetaInfo)
+                      Content (= CertificateContent)
+                      Signature
+
+    CertificateMetaInfo ::= META-INFO-TYPE TLV-LENGTH
+                              ContentType (= KEY)
+                              FreshnessPeriod (= ?)
+
+
+    CertificateContent ::= CONTENT-TYPE TLV-LENGTH
+                             CertificateDerPayload
+
+
+    // DER Encoding
+    CertificateDerPayload ::= SEQUENCE {
+        validity            Validity,
+        subject             Name,
+        subjectPubKeyInfo   SubjectPublicKeyInfo,
+        extension           Extensions OPTIONAL   }
+
+    Validity ::= SEQUENCE {
+        notBefore           Time,
+        notAfter            Time   }
+
+    Time ::= CHOICE {
+        GeneralizedTime   }
+
+    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 `RFC 3280 <http://www.ietf.org/rfc/rfc3280.txt>`_ for more details about DER field
+definitions.
+
+Signing
+-------
+
+Key Management
+%%%%%%%%%%%%%%
+
+Create Identity/Keys/Certificate
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The simplest way to initialize an identity and its key and certificate is to call
+:ndn-cxx:`KeyChain::createIdentity`
 
 .. code-block:: cpp
 
     KeyChain keyChain;
-    Name identity("/ndn/test/alice");
+    Name defaultCertName = keyChain.createIdentity(identity);
 
-    Name certificateName = keyChain.createIdentity(identity);
-
-``KeyChain::createIdentity`` returns the default certificate name of the
-supplied identity, and always assures that the supplied identity has a
-default key and a default certificate. If the default key of the
-identity does not exist, ``createIdentity`` will create one. If the
-default certificate of the identity does not exist, ``createIdentity``
-will generate a self-signed certificate of the default key as the
-default certificate.
-
-System Default Identity
-~~~~~~~~~~~~~~~~~~~~~~~
-
-There is a default key for a particular identity, and a default identity
-certificate for a particular key. And, there is also a **default
-identity** for the system, which is the user of the system. The default
-identity can be configured using ndnsec tools only. You cannot configure
-through the security library API.
-
-Get and Set Default Keys/Certificates
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you know the exact names of keys and certificates, you can call
-``KeyChain::getPublicKey`` and ``KeyChain::getCertificate``.
-
-.. code-block:: cpp
-
-    KeyChain keyChain;
-    Name aliceKeyName("/ndn/test/alice/ksk-1394129695025");
-    Name aliceCertName("/ndn/test/KEY/alice/ksk-1394129695025/ID-CERT/%FD%01D%98%9A%F2%3F");
-
-    shared_ptr<PublicKey> aliceKey = keyChain.getPublicKey(aliceKeyName);
-    shared_ptr<IdentityCertificate> aliceCert = keyChain.getCertificate(aliceCertName);
-
-It might be difficult to remember the exact name of keys and
-certificates, but it might be easier to remember identity names. The
-security library provides a list of methods to locate the default key
-name and certificate name of an identity.
-
-.. code-block:: cpp
-
-    KeyChain keyChain;
-    Name alice("/ndn/test/alice");
-
-    Name aliceKeyName = keyChain.getDefaultKeyNameForIdentity(alice);
-    Name aliceCertName = keyChain.getDefaultCertificateNameForKey(aliceKeyName);
-
-    /* following code is equivalent to the two lines above */
-    Name aliceCertName2 = keyChain.getDefaultCertificateNameForIdentity(alice);
-
-You can also manually set default key for an identity and default
-certificate for a key through KeyChain.
-
-.. code-block:: cpp
-
-    KeyChain keyChain;
-
-    Name aliceKeyName("/ndn/test/alice/ksk-1394129695025");
-    Name aliceCertName("/ndn/test/KEY/alice/ksk-1394129695025/ID-CERT/%FD%01D%98%9A%F2%3F");
-
-    keyChain.setDefaultKeyNameForIdentity(aliceKeyName);
-    keyChain.getDefaultCertificateNameForKey(aliceCertName);
+This method guarantees that the default key and certificate of the supplied identity
+always exist in the KeyChain.  This method checks if the supplied identity has already had
+a default key and a default certificate and returns the default certificate name if
+exists.  If the default certificate is missing, KeyChain will automatically create a
+self-signed certificate of the default key.  If the default key is missing, KeyChain will
+automatically create a new key and set it as the default key and create a self-signed
+certificate as well.
 
 Create Keys Manually
 ~~~~~~~~~~~~~~~~~~~~
 
-You can call ``KeyChain::generateRSAKeyPair`` to generate an RSA key
-pair. Note that generated key pair is not set as the default key of the
-identity, so you need to set it manually by calling
-``KeyChain::setDefaultKeyNameForIdentity``. There is also a helper
-method "KeyChain::generateRSAKeyPairAsDefault", which combines the two
-steps into one.
+One can call :ndn-cxx:`KeyChain::generateRsaKeyPair` to generate an RSA key pair or
+:ndn-cxx:`KeyChain::generateEcdsaKeyPair` to generate an ECDSA key.  Note that generated
+key pair is not set as the default key of the identity, so you need to set it manually by
+calling :ndn-cxx:`KeyChain::setDefaultKeyNameForIdentity`. There is also a helper method
+:ndn-cxx:`KeyChain::generateRsaKeyPairAsDefault`, which combines the two steps into one.
 
 .. code-block:: cpp
 
@@ -119,13 +145,14 @@
     Name aliceKeyName = keyChain.generateRSAKeyPair(alice);
     keyChain.setDefaultKeyNameForIdentity(aliceKeyName);
 
-    Name aliceKeyName2 = keyChain.generateRSAKeyPairAsDefault(alice); // Now the key with the name aliceKeyName2 becomes alice's default key
+    // Now the key with the name aliceKeyName2 becomes alice's default key
+    Name aliceKeyName2 = keyChain.generateRSAKeyPairAsDefault(alice);
 
 Create Identity Certificate Manually
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If you have created a key pair, you can generate a self-signed
-certificate for the key by calling ``KeyChain::selfSign``.
+If you have created a key pair, you can generate a self-signed certificate for the key by
+calling :ndn-cxx:`KeyChain::selfSign`.
 
 .. code-block:: cpp
 
@@ -134,227 +161,199 @@
 
     shared_ptr<IdentityCertificate> aliceCert = keyChain.selfSign(aliceKeyName);
 
-You can sign a public key using a different key, but this signing
-process may take several steps. Note that this time, the signing key is
-vouching for the signed key, so you need to specify more details, such
-as the validity, subject descriptions. The first step is to prepare the
-unsigned identity certificate by calling
-``KeyChain::prepareUnsignedIdentityCertificate``. And the second step is
-to sign the identity certificate. We will talk about the signing methods
-in `Packet Signing <#packet_signing>`__.
+You can sign a public key using a different key:
 
 .. code-block:: cpp
 
     KeyChain keyChain;
 
-    Name signingIdentity("/ndn/test");
-    Name aliceKeyName("/ndn/test/alice/ksk-1394129695025");
-    MillisecondsSince1970 notBefore = getNow();
-    MillisecondsSince1970 notAfter = notBefore + 630720000;
-    vector<CertificateSubjectDescription> subjectDescription;
-    subjectDescription.push_back(CertificateSubjectDescription("2.5.4.41", "Alice")); // push any subject description into the list.
+    shared_ptr<IdentityCertificate> certificate =
+      keyChain.prepareUnsignedIdentityCertificate(publicKeyName, publicKey,
+                                                  signingIdentity,
+                                                  notBefore, notAfter,
+                                                  subjectDescription, prefix
 
-    shared_ptr<IdentityCertificate> = aliceCert
-      keyChain.prepareUnsignedIdentityCertificate(aliceKeyName, signingIdentity, notBefore, notAfter, subjectDescription);
+    keyChain.signByIdentity(*certificate, signingIdentity);
 
-    keyChain.signByIdentity(*aliceCert, signingIdentity);
+Signing Data
+%%%%%%%%%%%%
 
-Packet Signing
---------------
+Although the security library does not have the intelligence to automatically determine
+the signing key for each data packet, it still provides a mechanism, called **Default
+Signing Settings**, to facilitate signing process.
 
-When keys and certificates are ready for use, you can sign packet using
-them. There are two ways to sign a packet:
+The basic signing process in the security library would be like this: create :ndn-cxx:`KeyChain`
+instance and supply the data packet and signing certificate name to :ndn-cxx:`KeyChain::sign`
+method.
 
-1. by specifying the name of the identity certificate belonging to the
-   signing key.
-2. by specifying the identity to which the signing key belongs
+.. code-block:: cpp
 
-Sign With Certificate Name
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+    KeyChain keyChain;
+    keyChain.sign(dataPacket, signingCertificateName);
 
-If we specify the exact certificate name when signing a packet, the
-certificate name (without version number) is put into the KeyLocator TLV
-in the SignatureInfo. KeyChain will look up the corresponding private
-key in the Trusted Platform Module (TPM), and use the private key to
-generate the signature.
+The :ndn-cxx:`KeyChain` instance will
+
+- construct ``SignatureInfo`` using the signing certificate name;
+- look up the corresponding private key in :ndn-cxx:`TPM <SecTpm>`;
+- sign the data packet if the private key exists.
+
+The basic process, however, requires application developers to supply the exact
+certificate name.  Such a process has two shortages: first, it might be difficult to
+remember the certificate name; second, application developers have to be aware of
+certificate update and key roll-over.  Therefore, the security library provides another
+signing process in which application developers only need to supply the signing identity:
+
+.. code-block:: cpp
+
+    KeyChain keyChain;
+    keyChain.signByIdentity(dataPacket, signingIdentity);
+
+The :ndn-cxx:`KeyChain` instance will
+
+- determine the default key of the signing identity;
+- determine the default certificate of the key;
+- construct ``SignatureInfo`` using the default certificate name;
+- look up the corresponding private key in :ndn-cxx:`TPM <SecTpm>`;
+- sign the data packet if the private key exists.
+
+The process above requires that each identity has a default key and that each key has a
+default certificate.  All these default settings is managed in :ndn-cxx:`PIB
+<SecPublicInfo>`, one can get/set these default settings through :ndn-cxx:`KeyChain`
+directly:
+
+.. code-block:: cpp
+
+    KeyChain keyChain;
+    Name defaultKeyName = keyChain.getDefaultKeyNameForIdentity(identity);
+    Name defaultCertName = keyChain.getDefaultCertificateNameForKey(keyName);
+
+    keyChain.setDefaultKeyNameForIdentity(keyName);
+    keyChain.setDefaultCertificateNameForKey(certificateName);
+
+There is even a default identity which will be used when no identity information is
+supplied in signing method:
+
+.. code-block:: cpp
+
+    KeyChain keyChain;
+    keyChain.sign(dataPacket);
+
+And default identity can be got/set through :ndn-cxx:`KeyChain` as well:
+
+.. code-block:: cpp
+
+    KeyChain keyChain;
+    Name defaultIdentity = keyChain.getDefaultIdentity();
+    keyChain.setDefaultIdentity(identity);
+
+
+Signing Interests
+%%%%%%%%%%%%%%%%%
+
+The process of signing Interests according to the :doc:`Signed Interest specification
+<signed-interest>` is exactly the same as the process of signing Data packets:
 
 .. code-block:: cpp
 
     KeyChain keyChain;
 
-    Name aliceCertName("/ndn/test/KEY/alice/ksk-1394129695025/ID-CERT/%FD%01D%98%9A%F2%3F");
-    Data data("/ndn/test/alice/test-data");
+    keyChain.sign(interest, signingCertName);
+    keyChain.signByIdentity(interest, signingIdentity);
+    keyChain.sign(interest);
 
-    keyChain.sign(data, aliceCertName);
+Validation
+----------
 
-When ``KeyChain::sing`` returns, the SignatureInfo and SignatureValue
-TLVs of the supplied data will be set.
-
-Sign With Identity Name
-~~~~~~~~~~~~~~~~~~~~~~~
-
-If we only specify the identity name when signing a packet, the name of
-the identity's default certificate will be put into the KeyLocator TLV
-in the SingatureInfo, and the identity's default key is used to sign the
-packet. Please make sure the default key and certificates of the signing
-identity is initialized correctly before signing, otherwise, KeyChain
-will create key and self-signed certificate for signing (which is not
-quite useful).
+Interest and Data validation is done through a **Validator**. :ndn-cxx:`Validator` is a virtual
+class, two pure virtual methods must be implemented in order to construct a working
+validator:
 
 .. code-block:: cpp
 
-    KeyChain keyChain;
-
-    Name alice("/ndn/test/alice");
-    Data data("/ndn/test/alice/test-data");
-
-    keyChain.signByIdentity(data, alice);
-
-Sign Interest Packet
-~~~~~~~~~~~~~~~~~~~~
-
-Signing an interest packet is the same as signing a Data packet. The
-only difference is that the SignatureInfo And SignatureValue TLV are
-encoded as the last two components of the interest name.
-
-Packet Validation
------------------
-
-Packet validation is done through a **Validator**. Validator is a
-virtual class, two pure virtual methods must be implemented in order to
-construct a working validator:
-
-.. code-block:: cpp
-
-    class Validator {
+    class Validator
+    {
       ...
     protected:
       virtual void
-      checkPolicy (const Data& data,
-                   int stepCount,
-                   const OnDataValidated &onValidated,
-                   const OnDataValidationFailed &onValidationFailed,
-                   std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
+      checkPolicy(const Data& data,
+                  int nSteps,
+                  const OnDataValidated& onValidated,
+                  const OnDataValidationFailed& onValidationFailed,
+                  std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
 
       virtual void
-      checkPolicy (const Interest& interest,
-                   int stepCount,
-                   const OnInterestValidated &onValidated,
-                   const OnInterestValidationFailed &onValidationFailed,
-                   std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
-    ...
-
-What you need to do inside these two methods is to check whether the
-packet and signer comply with your policies, and whether their signature
-can be verified. If the packet can be validated, you should call the
-``onValidated`` callback function to trigger packet processing,
-otherwise the ``onValidationFailed`` callback should be invoked. If you
-need more information (e.g., other certificates), you can construct
-several ``ValidationRequest`` and push them into nextSteps.
-
-.. code-block:: cpp
-
-    class ValidationRequest {
-    public:
-      Interest m_interest;                      // An interest packet to fetch the requested data.
-      OnDataValidated m_onValidated;            // A callback function if the requested certificate is validated.
-      OnDataValidationFailed m_onDataValidated; // A callback function if the requested certificate validation fails.
-      int m_retry;                              // The number of retrials when there is an interest timeout.
-      int m_stepCount;                          // The count of validation steps.
+      checkPolicy(const Interest& interest,
+                  int nSteps,
+                  const OnInterestValidated& onValidated,
+                  const OnInterestValidationFailed& onValidationFailed,
+                  std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
+      ...
     };
 
-Security library also provides an ``Validator``, ``ValidatorRegex``
-which has already implemented the two methods (basically for Data policy
-checking, the Interest policy checking method always calls
-``onValidationFailed``).
+What should be implemented in these two methods is to check:
+
+- whether the packet and signer comply with trust policies;
+- whether their signature can be verified.
+
+If the packet can be validated, the ``onValidated`` callback should be invoked, otherwise
+the ``onValidationFailed`` callback should be invoked.  If more information (e.g., other
+certificates) is needed, express the request for missing information in one or more
+``ValidationRequest`` and push them into ``nextSteps``.
 
 .. code-block:: cpp
 
-    class ValidatorRegex : public Validator
+    class ValidationRequest
     {
     public:
-      ...
-
-      void
-      addDataVerificationRule(shared_ptr<SecRuleRelative> rule);
-
-      void
-      addTrustAnchor(shared_ptr<IdentityCertificate> certificate);
-
-      ...
+      Interest m_interest;                      // The Interest for the requested data/certificate.
+      OnDataValidated m_onValidated;            // Callback when the retrieved certificate is authenticated.
+      OnDataValidationFailed m_onDataValidated; // Callback when the retrieved certificate cannot be authenticated.
+      int m_nRetries;                           // The number of retries when the interest times out.
+      int m_nStep;                              // The number of validation steps that have been performed.
     };
 
-With ``ValidatorRegex``, you can specify the validation rules in terms
-of [[Regex\|NDN Regular Expression]] via
-``ValidatorRegex::addDataVerificationRule``, and set trust anchor via
-``ValidatorRegex::addTrustAnchor``.
-
-How to specify regex-based validation rule
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To specify a ``SecRuleRelative``, you needs to specify two NDN regular
-expressions: one for data name matching, and the other for KeyLocator
-matching. For each regex, you also need to specify the back reference
-pattern to extract parts of the name. Moreover, you need to specify the
-relation between two extracted patterns. For example, a typical
-hierarchical rule can be written as
+Besides the two ``Validator::checkPolicy`` methods, the ``Validator`` also provides three
+hooks to control packet validation in a finer granularity.
 
 .. code-block:: cpp
 
-    SecRuleRelative rule("^(<>*)$", "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
-                         ">", "\\1", "\\1\\2", true);
+    class Validator
+    {
+      ...
+    protected:
+      virtual shared_ptr<const Data>
+      preCertificateValidation(const Data& data);
 
-This rule indicates that the data name must be under the signer's
-namespace.
+      virtual void
+      onTimeout(const Interest& interest,
+                int nRemainingRetries,
+                const OnFailure& onFailure,
+                const shared_ptr<ValidationRequest>& validationRequest);
 
-How to use validator
-~~~~~~~~~~~~~~~~~~~~
-
-Here is an example of how to use the validator
-
-.. code-block:: cpp
-
-    class Example {
-    public:
-      Example(ndn::shared_ptr<ndn::Face> face>)
-        : m_face(face)
-      {
-        ndn::shared_ptr<ndn::ValidatorRegex> validator(new ndn::ValidatorRegex(m_face));
-        validator->addDataVerificationRule(ndn::make_shared<ndn::SecRuleRelative>("^(<>*)$",
-                                                                                  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
-                                                                                  ">", "\\1", "\\1\\2", true));
-        ndn::shared_ptr<ndn::IdentityCertificate> anchor = ndn::io::load<IdentityCertificate>("ndn-root.cert");
-        validator->addTrustAnchor(anchor);
-        m_validator = validator;
-      }
-
-      virtual
-      ~Example() {}
-
-      void
-      sendInterest()
-      {
-        Interest interest ("/ndn/test/data");
-        m_face->expressInterest(interest,
-                                bind(&Example::onData, this, _1, _2),
-                                bind(&Example::onTimeout, this, _1));
-      }
-
-      void
-      onData(const ndn::Interest& interest, const ndn::Data& data)
-      {
-        m_validator->validate(data,
-                              ndn::bind(&Example::onValidated, this, _1),
-                              ndn::bind(&Example::onValidationFailed, this, _1, _2));
-      }
-
-      void onTimeout(const ndn::Interest& interest) {}
-
-      void onValidated(const ndn::shared_ptr<const ndn::Data>& data) {}
-
-      void onValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const std::string& failInfo) {}
-
-    private:
-      ndn::shared_ptr<ndn::Face> m_face;
-      ndn::shared_ptr<ndn::Validator> m_validator;
+      virtual void
+      afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
+                       const OnFailure& onFailure);
+      ...
     };
+
+``Validator::preCertificateValidation`` is triggered before validating requested
+certificate.  The Data supplied matches the interest in the ``ValidationRequest``.  It may
+be certificate or a data encapsulating certificate.  This hook returns a data (actually
+certificate) that is will be passed as Data into ``Validator::validate``;
+
+``Validator::onTimeout`` is triggered when interest for certificate times out.  The logic
+to handle the timeout can be implemented in this hook.  One could invoke onFailure or
+re-express the interest.
+
+``Validator::afterCheckPolicy`` is invoked after ``Validator::checkPolicy`` is done.  One
+can implement the logic of how to process the set of ValidationRequests according to its
+trust model.
+
+Configuration-based Validator
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+In most cases, the trust model of applications are simple.  However, it is not trivial to
+implement the two ``Validator::checkPolicy`` methods.  Therefore, we provide a more
+developer-friendly configuration-based validator, ``ValidatorConfig``.  With
+``ValidatorConfig``, one can express the trust model using a policy language in a
+configuration file.  See :doc:`security-validator-config` for more details.