Update validation related codes to security v2
Change-Id: I5467b87092820666c04f22623f0f1665ce9a1194
diff --git a/src/mgmt/management-tool.cpp b/src/mgmt/management-tool.cpp
index e74c601..6610a13 100644
--- a/src/mgmt/management-tool.cpp
+++ b/src/mgmt/management-tool.cpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2014-2017, Regents of the University of California.
*
* This file is part of NDNS (Named Data Networking Domain Name Service).
@@ -21,6 +21,7 @@
#include "logger.hpp"
#include "ndns-label.hpp"
#include "ndns-tlv.hpp"
+#include "util/cert-helper.hpp"
#include <string>
#include <iomanip>
@@ -32,103 +33,141 @@
#include <ndn-cxx/util/regex.hpp>
#include <ndn-cxx/util/indented-stream.hpp>
-#include <ndn-cxx/encoding/oid.hpp>
-#include <ndn-cxx/security/v1/cryptopp.hpp>
+#include <ndn-cxx/util/io.hpp>
#include <ndn-cxx/link.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/security/transform.hpp>
+
namespace ndn {
namespace ndns {
NDNS_LOG_INIT("ManagementTool")
+using security::transform::base64Encode;
+using security::transform::streamSink;
+using security::transform::bufferSource;
+using security::v2::Certificate;
+using security::Identity;
+using security::Key;
+
ManagementTool::ManagementTool(const std::string& dbFile, KeyChain& keyChain)
: m_keyChain(keyChain)
, m_dbMgr(dbFile)
{
}
-void
-ManagementTool::createZone(const Name &zoneName,
+Zone
+ManagementTool::createZone(const Name& zoneName,
const Name& parentZoneName,
const time::seconds& cacheTtl,
const time::seconds& certValidity,
const Name& kskCertName,
- const Name& dskCertName)
+ const Name& dskCertName,
+ const Name& dkeyCertName)
{
bool isRoot = zoneName == ROOT_ZONE;
+ Name zoneIdentityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
//check preconditions
Zone zone(zoneName, cacheTtl);
if (m_dbMgr.find(zone)) {
- throw Error(zoneName.toUri() + " is already presented in the NDNS db");
+ BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is already presented in the NDNS db"));
}
if (!isRoot && parentZoneName.equals(zoneName)) {
- throw Error("Parent zone name can not be the zone itself");
+ BOOST_THROW_EXCEPTION(Error("Parent zone name can not be the zone itself"));
}
if (!isRoot && !parentZoneName.isPrefixOf(zoneName)) {
- throw Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri());
+ BOOST_THROW_EXCEPTION(Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri()));
}
// if dsk is provided, there is no need to check ksk
if (dskCertName != DEFAULT_CERT) {
- if (!matchCertificate(dskCertName, zoneName)) {
- throw Error("Cannot verify DSK certificate");
+ if (!matchCertificate(dskCertName, zoneIdentityName)) {
+ BOOST_THROW_EXCEPTION(Error("Cannot verify DSK certificate"));
}
}
else if (kskCertName != DEFAULT_CERT) {
- if (!matchCertificate(kskCertName, zoneName)) {
- throw Error("Cannot verify KSK certificate");
+ if (!matchCertificate(kskCertName, zoneIdentityName)) {
+ BOOST_THROW_EXCEPTION(Error("Cannot verify KSK certificate"));
}
}
- if (kskCertName == DEFAULT_CERT && isRoot) {
- throw Error("Cannot generate KSK for root zone");
+ if (dkeyCertName == DEFAULT_CERT && isRoot) {
+ BOOST_THROW_EXCEPTION(Error("Cannot generate dkey for root zone"));
}
- //first generate KSK and DSK to the keyChain system, and add DSK as default
- NDNS_LOG_INFO("Start generating KSK and DSK and their corresponding certificates");
- Name dskName;
- shared_ptr<IdentityCertificate> dskCert;
- if (dskCertName == DEFAULT_CERT) {
- // if no dsk provided, then generate a dsk either signed by ksk auto generated or user provided
- time::system_clock::TimePoint notBefore = time::system_clock::now();
- time::system_clock::TimePoint notAfter = notBefore + certValidity;
- shared_ptr<IdentityCertificate> kskCert;
-
- if (kskCertName == DEFAULT_CERT) {
- //create KSK's certificate
- Name kskName = m_keyChain.generateRsaKeyPair(zoneName, true);
- std::vector<CertificateSubjectDescription> kskDesc;
- kskCert = m_keyChain.prepareUnsignedIdentityCertificate(kskName, zoneName, notBefore,
- notAfter, kskDesc, parentZoneName);
- kskCert->setFreshnessPeriod(cacheTtl);
-
- m_keyChain.selfSign(*kskCert);
- m_keyChain.addCertificate(*kskCert);
- NDNS_LOG_INFO("Generated KSK: " << kskCert->getName());
- }
- else {
- kskCert = m_keyChain.getCertificate(kskCertName);
- }
-
- dskName = m_keyChain.generateRsaKeyPairAsDefault(zoneName, false);
- //create DSK's certificate
- std::vector<CertificateSubjectDescription> dskDesc;
- dskCert = m_keyChain.prepareUnsignedIdentityCertificate(dskName, zoneName, notBefore, notAfter,
- dskDesc, zoneName);
- dskCert->setFreshnessPeriod(cacheTtl);
- m_keyChain.sign(*dskCert, kskCert->getName());
- m_keyChain.addCertificateAsKeyDefault(*dskCert);
- NDNS_LOG_INFO("Generated DSK: " << dskCert->getName());
+ // Generate a parentZone's identity to generate a D-Key.
+ // This D-key will be passed to parent zone and resigned.
+ Name dkeyIdentityName;
+ if (dkeyCertName == DEFAULT_CERT) {
+ dkeyIdentityName = Name(parentZoneName).append(label::NDNS_CERT_QUERY)
+ .append(zoneName.getSubName(parentZoneName.size()));
}
else {
- dskCert = m_keyChain.getCertificate(dskCertName);
- dskName = dskCert->getPublicKeyName();
- m_keyChain.setDefaultKeyNameForIdentity(dskName);
- m_keyChain.setDefaultCertificateNameForKey(dskCert->getName());
+ dkeyIdentityName = CertHelper::getIdentityNameFromCert(dkeyCertName);
+ }
+ NDNS_LOG_INFO("Generated D-Key's identityName: " + dkeyIdentityName.toUri());
+
+ Name dskName;
+ Key ksk;
+ Key dsk;
+ Key dkey;
+ Certificate dskCert;
+ Certificate kskCert;
+ Certificate dkeyCert;
+ Identity zoneIdentity = m_keyChain.createIdentity(zoneIdentityName);
+ Identity dkeyIdentity = m_keyChain.createIdentity(dkeyIdentityName);
+
+ if (dkeyCertName == DEFAULT_CERT) {
+ dkey = m_keyChain.createKey(dkeyIdentity);
+ m_keyChain.deleteCertificate(dkey, dkey.getDefaultCertificate().getName());
+
+ dkeyCert = CertHelper::createCertificate(m_keyChain, dkey, dkey, label::CERT_RR_TYPE.toUri(), time::days(90));
+ dkeyCert.setFreshnessPeriod(cacheTtl);
+ m_keyChain.addCertificate(dkey, dkeyCert);
+ NDNS_LOG_INFO("Generated DKEY: " << dkeyCert.getName());
+
+ }
+ else {
+ dkeyCert = CertHelper::getCertificate(m_keyChain, dkeyIdentityName, dkeyCertName);
+ dkey = dkeyIdentity.getKey(dkeyCert.getKeyName());
+ }
+
+ if (kskCertName == DEFAULT_CERT) {
+ ksk = m_keyChain.createKey(zoneIdentity);
+ // delete automatically generated certificates,
+ // because its issue is 'self' instead of CERT_RR_TYPE
+ m_keyChain.deleteCertificate(ksk, ksk.getDefaultCertificate().getName());
+ kskCert = CertHelper::createCertificate(m_keyChain, ksk, dkey, label::CERT_RR_TYPE.toUri(), time::days(90));
+ kskCert.setFreshnessPeriod(cacheTtl);
+ m_keyChain.addCertificate(ksk, kskCert);
+ NDNS_LOG_INFO("Generated KSK: " << kskCert.getName());
+ }
+ else {
+ // ksk usually might not be the default key of a zone
+ kskCert = CertHelper::getCertificate(m_keyChain, zoneIdentityName, kskCertName);
+ ksk = zoneIdentity.getKey(kskCert.getKeyName());
+ }
+
+ if (dskCertName == DEFAULT_CERT) {
+ // if no dsk provided, then generate a dsk either signed by ksk auto generated or user provided
+ dsk = m_keyChain.createKey(zoneIdentity);
+ m_keyChain.deleteCertificate(dsk, dsk.getDefaultCertificate().getName());
+ dskCert = CertHelper::createCertificate(m_keyChain, dsk, ksk, label::CERT_RR_TYPE.toUri(), certValidity);
+ dskCert.setFreshnessPeriod(cacheTtl);
+ // dskCert will become the default certificate, since the default cert has been deleted.
+ m_keyChain.addCertificate(dsk, dskCert);
+ m_keyChain.setDefaultKey(zoneIdentity, dsk);
+ NDNS_LOG_INFO("Generated DSK: " << dskCert.getName());
+ }
+ else {
+ dskCert = CertHelper::getCertificate(m_keyChain, zoneIdentityName, dskCertName);
+ dsk = zoneIdentity.getKey(dskCert.getKeyName());
+ m_keyChain.setDefaultKey(zoneIdentity, dsk);
+ m_keyChain.setDefaultCertificate(dsk, dskCert);
}
//second add zone to the database
@@ -136,8 +175,18 @@
addZone(zone);
//third create ID-cert
- NDNS_LOG_INFO("Start creating DSK's ID-CERT");
- addIdCert(zone, dskCert, cacheTtl);
+ NDNS_LOG_INFO("Start adding Certificates to NDNS database");
+ addIdCert(zone, kskCert, cacheTtl, dskCert);
+ addIdCert(zone, dskCert, cacheTtl, dskCert);
+
+ NDNS_LOG_INFO("Start saving KSK and DSK's id to ZoneInfo");
+ m_dbMgr.setZoneInfo(zone, "ksk", kskCert.wireEncode());
+ m_dbMgr.setZoneInfo(zone, "dsk", dskCert.wireEncode());
+
+ NDNS_LOG_INFO("Start saving DKEY certificate id to ZoneInfo");
+ m_dbMgr.setZoneInfo(zone, "dkey", dkeyCert.wireEncode());
+
+ return zone;
}
void
@@ -146,7 +195,7 @@
//check pre-conditions
Zone zone(zoneName);
if (!m_dbMgr.find(zone)) {
- throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+ BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is not presented in the NDNS db"));
}
//first remove all rrsets of this zone from local ndns database
@@ -162,37 +211,34 @@
void
ManagementTool::exportCertificate(const Name& certName, const std::string& outFile)
{
- //search for the certificate, start from KeyChain then local NDNS database
- shared_ptr<IdentityCertificate> cert;
- if (m_keyChain.doesCertificateExist(certName)) {
- cert = m_keyChain.getCertificate(certName);
+ // only search in local NDNS database
+ security::v2::Certificate cert;
+ shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<NDNS>(<>+)<CERT><>");
+ if (!regex->match(certName)) {
+ BOOST_THROW_EXCEPTION(Error("Certificate name is illegal"));
+ return;
+ }
+
+ Name zoneName = regex->expand("\\1");
+ Name identityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
+ Name label = regex->expand("\\2");
+
+ Zone zone(zoneName);
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(label::CERT_RR_TYPE);
+ if (m_dbMgr.find(rrset)) {
+ cert = security::v2::Certificate(rrset.getData());
}
else {
- shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
- if (regex->match(certName) != true) {
- throw Error("Certificate name is illegal");
- }
- Name zoneName = regex->expand("\\1");
- Name label = regex->expand("\\2");
-
- Zone zone(zoneName);
- Rrset rrset(&zone);
- rrset.setLabel(label);
- rrset.setType(label::CERT_RR_TYPE);
- if (m_dbMgr.find(rrset)) {
- Data data(rrset.getData());
- cert = make_shared<IdentityCertificate>(data);
- }
- else {
- throw Error("Cannot find the cert: " + certName.toUri());
- }
+ BOOST_THROW_EXCEPTION(Error("Cannot find the cert: " + certName.toUri()));
}
if (outFile == DEFAULT_IO) {
- ndn::io::save(*cert, std::cout);
+ ndn::io::save(cert, std::cout);
}
else {
- ndn::io::save(*cert, outFile);
+ ndn::io::save(cert, outFile);
NDNS_LOG_INFO("save cert to file: " << outFile);
}
}
@@ -253,7 +299,7 @@
ManagementTool::addRrset(Rrset& rrset)
{
if (rrset.getLabel().size() > 1) {
- throw Error("Cannot add rrset with label size > 1, should use addMultiLevelLabelRrset instead");
+ BOOST_THROW_EXCEPTION(Error("Cannot add rrset with label size > 1, should use addMultiLevelLabelRrset instead"));
}
// check that it does not override existing AUTH
@@ -280,26 +326,27 @@
{
//check precondition
Zone zone(zoneName);
+ Name zoneIdentityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
if (!m_dbMgr.find(zone)) {
- throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+ BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is not presented in the NDNS db"));
}
Name dskName;
Name dskCertName = inputDskCertName;
if (dskCertName == DEFAULT_CERT) {
- dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
- dskCertName = m_keyChain.getDefaultCertificateNameForKey(dskName);
+ dskName = CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, zoneIdentityName);
+ dskCertName = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, zoneIdentityName);
}
else {
- if (!matchCertificate(dskCertName, zoneName)) {
- throw Error("Cannot verify certificate");
+ if (!matchCertificate(dskCertName, zoneIdentityName)) {
+ BOOST_THROW_EXCEPTION(Error("Cannot verify certificate"));
}
}
if (inFile != DEFAULT_IO) {
boost::filesystem::path dir = boost::filesystem::path(inFile);
if (!boost::filesystem::exists(dir) || boost::filesystem::is_directory(dir)) {
- throw Error("Data: " + inFile + " does not exist");
+ BOOST_THROW_EXCEPTION(Error("Data: " + inFile + " does not exist"));
}
}
@@ -311,7 +358,7 @@
data = ndn::io::load<ndn::Data>(inFile, encoding);
if (data == nullptr) {
- throw Error("input does not contain a valid Data packet");
+ BOOST_THROW_EXCEPTION(Error("input does not contain a valid Data packet"));
}
if (needResign) {
@@ -335,16 +382,23 @@
rrset.setData(data->wireEncode());
checkRrsetVersion(rrset);
- NDNS_LOG_INFO("Added " << rrset);
+ NDNS_LOG_INFO("Adding rrset from file " << rrset);
m_dbMgr.insert(rrset);
}
+security::v2::Certificate
+ManagementTool::getZoneDkey(Zone& zone)
+{
+ std::map<std::string, Block> zoneInfo = m_dbMgr.getZoneInfo(zone);
+ return security::v2::Certificate(zoneInfo["dkey"]);
+}
+
void
ManagementTool::listZone(const Name& zoneName, std::ostream& os, const bool printRaw)
{
Zone zone(zoneName);
if (!m_dbMgr.find(zone)) {
- throw Error("Zone " + zoneName.toUri() + " is not found in the database");
+ BOOST_THROW_EXCEPTION(Error("Zone " + zoneName.toUri() + " is not found in the database"));
}
//first output the zone name
@@ -383,7 +437,7 @@
|| re.getContentType() == NDNS_KEY
|| re.getContentType() == NDNS_AUTH ? 1 : re.getRrs().size();
- const std::vector<Block> &rrs = re.getRrs();
+ const std::vector<Block>& rrs = re.getRrs();
if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
os << "; rrset=" << rrset.getLabel().toUri()
@@ -405,7 +459,6 @@
os << rrset.getType().toUri();
if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
- using namespace CryptoPP;
if (rrset.getType() == label::TXT_RR_TYPE) {
os.write(reinterpret_cast<const char*>(rrs[i].value()), rrs[i].value_size());
os << std::endl;
@@ -415,20 +468,20 @@
if (re.getContentType() == NDNS_AUTH) {
const std::string authStr = "NDNS-Auth";
os << authStr;
- } else {
+ }
+ else {
Link link(rrset.getData());
- const Link::DelegationSet& ds = link.getDelegations();
+ const DelegationList& ds = link.getDelegationList();
for (const auto& i: ds) {
- std::string str = boost::lexical_cast<std::string>(i.first)
- + "," + i.second.toUri() + ";";
+ std::string str = std::to_string(i.preference);
+ + "," + i.name.toUri() + ";";
os << str;
}
}
os << std::endl;
}
else {
- StringSource ss(rrs[i].wire(), rrs[i].size(), true,
- new Base64Encoder(new FileSink(os), true, 64));
+ bufferSource(rrs[i].wire(), rrs[i].size()) >> base64Encode() >> streamSink(os);
}
}
}
@@ -442,17 +495,15 @@
if (printRaw && (re.getContentType() == NDNS_BLOB
|| re.getContentType() == NDNS_KEY)) {
- util::IndentedStream istream(os, "; ");
+ ndn::util::IndentedStream istream(os, "; ");
if (re.getRrType() == label::CERT_RR_TYPE) {
- shared_ptr<Data> data = re.toData();
- IdentityCertificate cert(*data);
- cert.printCertificate(istream);
+ security::v2::Certificate cert(rrset.getData());
+ os << cert;
+ // cert.printCertificate(istream);
}
else {
- using namespace CryptoPP;
- StringSource ss(re.getAppContent().wire(), re.getAppContent().size(), true,
- new Base64Encoder(new FileSink(istream), true, 64));
+ bufferSource(re.getAppContent().wire(), re.getAppContent().size()) >> base64Encode() >> streamSink(os);
}
}
os << std::endl;
@@ -477,11 +528,12 @@
os.setf(os.left);
os.width(nameWidth + 2);
os << zone.getName().toUri();
+ Name zoneIdentity = Name(zone.getName()).append(label::NDNS_CERT_QUERY);
os << "; default-ttl=" << zone.getTtl().count();
- os << " default-key=" << m_keyChain.getDefaultKeyNameForIdentity(zone.getName());
+ os << " default-key=" << CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, zoneIdentity);
os << " default-certificate="
- << m_keyChain.getDefaultCertificateNameForIdentity(zone.getName());
+ << CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, zoneIdentity);
os << std::endl;
}
}
@@ -518,39 +570,39 @@
return;
}
- using namespace CryptoPP;
- StringSource ss(rrset.getData().wire(), rrset.getData().size(), true,
- new Base64Encoder(new FileSink(os), true, 64));
+ bufferSource(rrset.getData().wire(), rrset.getData().size()) >> base64Encode() >> streamSink(os);
}
void
-ManagementTool::addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert,
- const time::seconds& ttl)
+ManagementTool::addIdCert(Zone& zone, const Certificate& cert,
+ const time::seconds& ttl,
+ const Certificate& dskCert)
{
- Rrset rrset(&zone);
+ Rrset rrsetKey(&zone);
size_t size = zone.getName().size();
- Name label = cert->getName().getSubName(size + 1, cert->getName().size() - size - 3);
- rrset.setLabel(label);
- rrset.setType(label::CERT_RR_TYPE);
- rrset.setTtl(ttl);
- rrset.setVersion(cert->getName().get(-1));
- rrset.setData(cert->wireEncode());
+ Name label = cert.getName().getSubName(size + 1, cert.getName().size() - size - 3);
+ rrsetKey.setLabel(label);
+ rrsetKey.setType(label::CERT_RR_TYPE);
+ rrsetKey.setTtl(ttl);
+ rrsetKey.setVersion(cert.getName().get(-1));
+ rrsetKey.setData(cert.wireEncode());
- if (m_dbMgr.find(rrset)) {
- throw Error("ID-CERT with label=" + label.toUri() +
- " is already presented in local NDNS databse");
+ if (m_dbMgr.find(rrsetKey)) {
+ BOOST_THROW_EXCEPTION(Error("CERT with label=" + label.toUri() +
+ " is already presented in local NDNS databse"));
}
+
+ m_dbMgr.insert(rrsetKey);
NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
<< label::CERT_RR_TYPE);
- m_dbMgr.insert(rrset);
}
void
ManagementTool::addZone(Zone& zone)
{
if (m_dbMgr.find(zone)) {
- throw Error("Zone with Name=" + zone.getName().toUri() +
- " is already presented in local NDNS databse");
+ BOOST_THROW_EXCEPTION(Error("Zone with Name=" + zone.getName().toUri() +
+ " is already presented in local NDNS databse"));
}
NDNS_LOG_INFO("Add zone with Name: " << zone.getName().toUri());
m_dbMgr.insert(zone);
@@ -569,26 +621,15 @@
bool
ManagementTool::matchCertificate(const Name& certName, const Name& identity)
{
- if (!m_keyChain.doesCertificateExist(certName)) {
- NDNS_LOG_WARN(certName.toUri() << " is not presented in KeyChain");
- return false;
+ security::Identity id = m_keyChain.getPib().getIdentity(identity);
+ for (const security::Key& key: id.getKeys()) {
+ try {
+ key.getCertificate(certName);
+ return true;
+ } catch (const std::exception&) {
+ }
}
-
- //check its public key information
- shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(certName);
- Name keyName = cert->getPublicKeyName();
-
- if (!identity.isPrefixOf(keyName) || identity.size()!=keyName.size()-1) {
- NDNS_LOG_WARN(keyName.toUri() << " is not a key of " << identity.toUri());
- return false;
- }
-
- if (!m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PRIVATE)) {
- NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not present in KeyChain");
- return false;
- }
-
- return true;
+ return false;
}
void
@@ -598,10 +639,12 @@
if (m_dbMgr.find(originalRrset)) {
// update only if rrset has a newer version
if (originalRrset.getVersion() == rrset.getVersion()) {
- throw Error("Duplicate: " + boost::lexical_cast<std::string>(originalRrset));
+ BOOST_THROW_EXCEPTION(Error("Duplicate: "
+ + boost::lexical_cast<std::string>(originalRrset)));
}
else if (originalRrset.getVersion() > rrset.getVersion()) {
- throw Error("Newer version exists: " + boost::lexical_cast<std::string>(originalRrset));
+ BOOST_THROW_EXCEPTION(Error("Newer version exists: "
+ + boost::lexical_cast<std::string>(originalRrset)));
}
m_dbMgr.remove(originalRrset);