security: Add ECDSA signature signing and validation
Change-Id: I2f193e9d643498a68579ae59a7f524ff446dcb9e
Refs: #1660
diff --git a/src/security/cryptopp.hpp b/src/security/cryptopp.hpp
index 3aac257..d7342cf 100644
--- a/src/security/cryptopp.hpp
+++ b/src/security/cryptopp.hpp
@@ -38,5 +38,8 @@
#include <cryptopp/pwdbased.h>
#include <cryptopp/rsa.h>
#include <cryptopp/sha.h>
+#include <cryptopp/eccrypto.h>
+#include <cryptopp/oids.h>
+#include <cryptopp/dsa.h>
#endif // NDN_SECURITY_CRYPTOPP_HPP
diff --git a/src/security/key-chain.cpp b/src/security/key-chain.cpp
index a04e58b..69d5b48 100644
--- a/src/security/key-chain.cpp
+++ b/src/security/key-chain.cpp
@@ -131,6 +131,14 @@
try
{
keyName = m_pib->getDefaultKeyNameForIdentity(identityName);
+
+ shared_ptr<PublicKey> key = m_pib->getPublicKey(keyName);
+
+ if (key->getKeyType() != params.getKeyType())
+ {
+ keyName = generateKeyPair(identityName, true, params);
+ m_pib->setDefaultKeyNameForIdentity(keyName);
+ }
}
catch (SecPublicInfo::Error& e)
{
@@ -154,7 +162,7 @@
}
Name
-KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
+KeyChain::generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
{
RsaKeyParams params(keySize);
@@ -165,6 +173,19 @@
return keyName;
}
+Name
+KeyChain::generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+ EcdsaKeyParams params(keySize);
+
+ Name keyName = generateKeyPair(identityName, isKsk, params);
+
+ m_pib->setDefaultKeyNameForIdentity(keyName);
+
+ return keyName;
+}
+
+
shared_ptr<IdentityCertificate>
KeyChain::prepareUnsignedIdentityCertificate(const Name& keyName,
const Name& signingIdentity,
@@ -266,19 +287,21 @@
Signature
KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
{
- if (!m_pib->doesCertificateExist(certificateName))
- throw SecPublicInfo::Error("Requested certificate [" +
- certificateName.toUri() + "] doesn't exist");
+ shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
+ shared_ptr<SignatureWithPublicKey> sig =
+ determineSignatureWithPublicKey(certificate->getPublicKeyInfo().getKeyType());
- SignatureSha256WithRsa signature;
- // implicit conversion should take care
- signature.setKeyLocator(certificateName.getPrefix(-1));
+ if (!static_cast<bool>(sig))
+ throw SecTpm::Error("unknown key type");
- // For temporary usage, we support RSA + SHA256 only, but will support more.
- signature.setValue(m_tpm->signInTpm(buffer, bufferLength, keyName, DIGEST_ALGORITHM_SHA256));
- return signature;
+ sig->setKeyLocator(certificate->getName().getPrefix(-1));
+ // For temporary usage, we support SHA256 only, but will support more.
+ sig->setValue(m_tpm->signInTpm(buffer, bufferLength,
+ certificate->getPublicKeyName(),
+ DIGEST_ALGORITHM_SHA256));
+
+ return *sig;
}
shared_ptr<IdentityCertificate>
@@ -317,11 +340,14 @@
if (!m_tpm->doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
throw SecTpm::Error("Private key does not exist");
- SignatureSha256WithRsa signature;
- signature.setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
+ shared_ptr<SignatureWithPublicKey> sig =
+ determineSignatureWithPublicKey(cert.getPublicKeyInfo().getKeyType());
- // For temporary usage, we support RSA + SHA256 only, but will support more.
- signPacketWrapper(cert, signature, keyName, DIGEST_ALGORITHM_SHA256);
+ if (!static_cast<bool>(sig))
+ throw SecTpm::Error("unknown key type");
+
+ sig->setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
+ signPacketWrapper(cert, *sig, keyName, DIGEST_ALGORITHM_SHA256);
}
shared_ptr<SecuredBag>
@@ -384,6 +410,32 @@
m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
}
+shared_ptr<SignatureWithPublicKey>
+KeyChain::determineSignatureWithPublicKey(KeyType keyType, DigestAlgorithm digestAlgorithm)
+{
+ switch (keyType)
+ {
+ case KEY_TYPE_RSA:
+ {
+ // For temporary usage, we support SHA256 only, but will support more.
+ if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
+ return shared_ptr<SignatureWithPublicKey>();
+
+ return make_shared<SignatureSha256WithRsa>();
+ }
+ case KEY_TYPE_ECDSA:
+ {
+ // For temporary usage, we support SHA256 only, but will support more.
+ if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
+ return shared_ptr<SignatureWithPublicKey>();
+
+ return make_shared<SignatureSha256WithEcdsa>();
+ }
+ default:
+ return shared_ptr<SignatureWithPublicKey>();
+ }
+}
+
void
KeyChain::setDefaultCertificateInternal()
{
@@ -422,7 +474,7 @@
}
void
-KeyChain::signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
+KeyChain::signPacketWrapper(Data& data, const Signature& signature,
const Name& keyName, DigestAlgorithm digestAlgorithm)
{
data.setSignature(signature);
@@ -436,7 +488,7 @@
}
void
-KeyChain::signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
+KeyChain::signPacketWrapper(Interest& interest, const Signature& signature,
const Name& keyName, DigestAlgorithm digestAlgorithm)
{
time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index 44ff1de..b6b9bbf 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -29,6 +29,7 @@
#include "key-params.hpp"
#include "secured-bag.hpp"
#include "signature-sha256-with-rsa.hpp"
+#include "signature-sha256-with-ecdsa.hpp"
#include "digest-sha256.hpp"
#include "../interest.hpp"
@@ -103,8 +104,10 @@
* @return The generated key name.
*/
inline Name
- generateRsaKeyPair(const Name& identityName, bool isKsk = false, int keySize = 2048);
+ generateRsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 2048);
+ inline Name
+ generateEcdsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 256);
/**
* @brief Generate a pair of RSA keys for the specified identity and set it as default key for
* the identity.
@@ -115,7 +118,11 @@
* @return The generated key name.
*/
Name
- generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, int keySize = 2048);
+ generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false,
+ uint32_t keySize = 2048);
+
+ Name
+ generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk, uint32_t keySize = 256);
/**
* @brief prepare an unsigned identity certificate
@@ -635,6 +642,15 @@
private:
/**
+ * @brief Determine signature type
+ *
+ * An empty pointer will be returned if there is no valid signature.
+ */
+ shared_ptr<SignatureWithPublicKey>
+ determineSignatureWithPublicKey(KeyType keyType,
+ DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256);
+
+ /**
* @brief Set default certificate if it is not initialized
*/
void
@@ -672,7 +688,7 @@
* @throws Tpm::Error
*/
void
- signPacketWrapper(Data& data, const SignatureSha256WithRsa& signature,
+ signPacketWrapper(Data& data, const Signature& signature,
const Name& keyName, DigestAlgorithm digestAlgorithm);
/**
@@ -685,7 +701,7 @@
* @throws Tpm::Error
*/
void
- signPacketWrapper(Interest& interest, const SignatureSha256WithRsa& signature,
+ signPacketWrapper(Interest& interest, const Signature& signature,
const Name& keyName, DigestAlgorithm digestAlgorithm);
@@ -705,12 +721,19 @@
}
inline Name
-KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, int keySize)
+KeyChain::generateRsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
{
RsaKeyParams params(keySize);
return generateKeyPair(identityName, isKsk, params);
}
+inline Name
+KeyChain::generateEcdsaKeyPair(const Name& identityName, bool isKsk, uint32_t keySize)
+{
+ EcdsaKeyParams params(keySize);
+ return generateKeyPair(identityName, isKsk, params);
+}
+
template<typename T>
void
KeyChain::sign(T& packet)
@@ -725,18 +748,8 @@
void
KeyChain::sign(T& packet, const Name& certificateName)
{
- if (!m_pib->doesCertificateExist(certificateName))
- throw SecPublicInfo::Error("Requested certificate [" +
- certificateName.toUri() + "] doesn't exist");
-
- SignatureSha256WithRsa signature;
- // implicit conversion should take care
- signature.setKeyLocator(certificateName.getPrefix(-1));
-
- // For temporary usage, we support RSA + SHA256 only, but will support more.
- signPacketWrapper(packet, signature,
- IdentityCertificate::certificateNameToPublicKeyName(certificateName),
- DIGEST_ALGORITHM_SHA256);
+ shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
+ sign(packet, *certificate);
}
template<typename T>
@@ -764,11 +777,35 @@
void
KeyChain::sign(T& packet, const IdentityCertificate& certificate)
{
- SignatureSha256WithRsa signature;
- signature.setKeyLocator(certificate.getName().getPrefix(-1));
+ switch (certificate.getPublicKeyInfo().getKeyType())
+ {
+ case KEY_TYPE_RSA:
+ {
+ // For temporary usage, we support SHA256 only, but will support more.
+ SignatureSha256WithRsa signature;
+ // implicit conversion should take care
+ signature.setKeyLocator(certificate.getName().getPrefix(-1));
- // For temporary usage, we support RSA + SHA256 only, but will support more.
- signPacketWrapper(packet, signature, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
+ signPacketWrapper(packet, signature,
+ certificate.getPublicKeyName(),
+ DIGEST_ALGORITHM_SHA256);
+ return;
+ }
+ case KEY_TYPE_ECDSA:
+ {
+ // For temporary usage, we support SHA256 only, but will support more.
+ SignatureSha256WithEcdsa signature;
+ // implicit conversion should take care
+ signature.setKeyLocator(certificate.getName().getPrefix(-1));
+
+ signPacketWrapper(packet, signature,
+ certificate.getPublicKeyName(),
+ DIGEST_ALGORITHM_SHA256);
+ return;
+ }
+ default:
+ throw SecPublicInfo::Error("unknown key type!");
+ }
}
}
diff --git a/src/security/sec-public-info-sqlite3.cpp b/src/security/sec-public-info-sqlite3.cpp
index a690bef..7e86773 100644
--- a/src/security/sec-public-info-sqlite3.cpp
+++ b/src/security/sec-public-info-sqlite3.cpp
@@ -27,6 +27,7 @@
#include "sec-public-info-sqlite3.hpp"
#include "identity-certificate.hpp"
#include "signature-sha256-with-rsa.hpp"
+#include "signature-sha256-with-ecdsa.hpp"
#include "../data.hpp"
#include <sqlite3.h>
@@ -479,10 +480,27 @@
{
// this will throw an exception if the signature is not the standard one
// or there is no key locator present
- SignatureSha256WithRsa signature(certificate.getSignature());
- std::string signerName = signature.getKeyLocator().getName().toUri();
+ switch (certificate.getSignature().getType())
+ {
+ case Tlv::SignatureSha256WithRsa:
+ {
+ SignatureSha256WithRsa signature(certificate.getSignature());
+ std::string signerName = signature.getKeyLocator().getName().toUri();
- sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
+ sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
+ break;
+ }
+ case Tlv::SignatureSha256WithEcdsa:
+ {
+ SignatureSha256WithEcdsa signature(certificate.getSignature());
+ std::string signerName = signature.getKeyLocator().getName().toUri();
+
+ sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
+ break;
+ }
+ default:
+ return;
+ }
}
catch (std::runtime_error& e)
{
diff --git a/src/security/sec-tpm-file.cpp b/src/security/sec-tpm-file.cpp
index 6634f68..03ce634 100644
--- a/src/security/sec-tpm-file.cpp
+++ b/src/security/sec-tpm-file.cpp
@@ -142,6 +142,51 @@
chmod(publicKeyFileName.c_str(), 0000444);
return;
}
+ case KEY_TYPE_ECDSA:
+ {
+ using namespace CryptoPP;
+
+ const EcdsaKeyParams& ecdsaParams = static_cast<const EcdsaKeyParams&>(params);
+
+ OID curveName;
+ switch (ecdsaParams.getKeySize())
+ {
+ case 256:
+ curveName = ASN1::secp256r1();
+ break;
+ case 384:
+ curveName = ASN1::secp384r1();
+ break;
+ default:
+ curveName = ASN1::secp256r1();
+ }
+
+ AutoSeededRandomPool rng;
+
+ ECDSA<ECP, SHA256>::PrivateKey privateKey;
+ DL_GroupParameters_EC<ECP> cryptoParams(curveName);
+ cryptoParams.SetEncodeAsOID(true);
+ privateKey.Initialize(rng, cryptoParams);
+
+ ECDSA<ECP, SHA256>::PublicKey publicKey;
+ privateKey.MakePublicKey(publicKey);
+ publicKey.AccessGroupParameters().SetEncodeAsOID(true);
+
+ string privateKeyFileName = keyFileName + ".pri";
+ Base64Encoder privateKeySink(new FileSink(privateKeyFileName.c_str()));
+ privateKey.DEREncode(privateKeySink);
+ privateKeySink.MessageEnd();
+
+ string publicKeyFileName = keyFileName + ".pub";
+ Base64Encoder publicKeySink(new FileSink(publicKeyFileName.c_str()));
+ publicKey.Save(publicKeySink);
+ publicKeySink.MessageEnd();
+
+ /*set file permission*/
+ chmod(privateKeyFileName.c_str(), 0000400);
+ chmod(publicKeyFileName.c_str(), 0000444);
+ return;
+ }
default:
throw Error("Unsupported key type!");
}
@@ -258,31 +303,79 @@
using namespace CryptoPP;
AutoSeededRandomPool rng;
- //Read private key
- ByteQueue bytes;
- FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(),
- true, new Base64Decoder);
- file.TransferTo(bytes);
- bytes.MessageEnd();
- RSA::PrivateKey privateKey;
- privateKey.Load(bytes);
+ //Read public key
+ shared_ptr<PublicKey> pubkeyPtr;
+ pubkeyPtr = getPublicKeyFromTpm(keyName);
- //Sign message
- switch (digestAlgorithm)
+ switch (pubkeyPtr->getKeyType())
{
- case DIGEST_ALGORITHM_SHA256:
+ case KEY_TYPE_RSA:
+ {
+ //Read private key
+ ByteQueue bytes;
+ FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(),
+ true, new Base64Decoder);
+ file.TransferTo(bytes);
+ bytes.MessageEnd();
+ RSA::PrivateKey privateKey;
+ privateKey.Load(bytes);
+
+ //Sign message
+ switch (digestAlgorithm)
+ {
+ case DIGEST_ALGORITHM_SHA256:
+ {
+ RSASS<PKCS1v15, SHA256>::Signer signer(privateKey);
+
+ OBufferStream os;
+ StringSource(data, dataLength,
+ true,
+ new SignerFilter(rng, signer, new FileSink(os)));
+
+ return Block(Tlv::SignatureValue, os.buf());
+ }
+ default:
+ throw Error("Unsupported digest algorithm!");
+ }
+ }
+ case KEY_TYPE_ECDSA:
{
- RSASS<PKCS1v15, SHA256>::Signer signer(privateKey);
+ //Read private key
+ ByteQueue bytes;
+ FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(),
+ true, new Base64Decoder);
+ file.TransferTo(bytes);
+ bytes.MessageEnd();
- OBufferStream os;
- StringSource(data, dataLength,
- true,
- new SignerFilter(rng, signer, new FileSink(os)));
+ //Sign message
+ switch (digestAlgorithm)
+ {
+ case DIGEST_ALGORITHM_SHA256:
+ {
+ ECDSA<ECP, SHA256>::PrivateKey privateKey;
+ privateKey.Load(bytes);
+ ECDSA<ECP, SHA256>::Signer signer(privateKey);
- return Block(Tlv::SignatureValue, os.buf());
+ OBufferStream os;
+ StringSource(data, dataLength,
+ true,
+ new SignerFilter(rng, signer, new FileSink(os)));
+
+ uint8_t buf[200];
+ size_t bufSize = DSAConvertSignatureFormat(buf, 200, DSA_DER,
+ os.buf()->buf(), os.buf()->size(),
+ DSA_P1363);
+
+ shared_ptr<Buffer> sigBuffer = make_shared<Buffer>(buf, bufSize);
+
+ return Block(Tlv::SignatureValue, sigBuffer);
+ }
+ default:
+ throw Error("Unsupported digest algorithm!");
+ }
}
default:
- throw Error("Unsupported digest algorithm!");
+ throw Error("Unsupported key type!");
}
}
catch (CryptoPP::Exception& e)
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index 031632d..f3a782b 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -396,6 +396,12 @@
keySize = rsaParams.getKeySize();
break;
}
+ case KEY_TYPE_ECDSA:
+ {
+ const EcdsaKeyParams& ecdsaParams = static_cast<const EcdsaKeyParams&>(params);
+ keySize = ecdsaParams.getKeySize();
+ break;
+ }
default:
throw Error("Fail to create a key pair: Unsupported key type");
}
@@ -1039,6 +1045,8 @@
switch (keyType) {
case KEY_TYPE_RSA:
return kSecAttrKeyTypeRSA;
+ case KEY_TYPE_ECDSA:
+ return kSecAttrKeyTypeECDSA;
default:
return 0;
}
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index 29a4801..df7b0e6 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -29,10 +29,11 @@
#include "cryptopp.hpp"
-using namespace std;
-
namespace ndn {
+static OID SECP256R1("1.2.840.10045.3.1.7");
+static OID SECP384R1("1.3.132.0.34");
+
Validator::Validator()
: m_hasFace(false)
, m_face(*static_cast<Face*>(0))
@@ -51,7 +52,7 @@
const OnInterestValidationFailed& onValidationFailed,
int nSteps)
{
- vector<shared_ptr<ValidationRequest> > nextSteps;
+ std::vector<shared_ptr<ValidationRequest> > nextSteps;
checkPolicy(interest, nSteps, onValidated, onValidationFailed, nextSteps);
if (!nextSteps.empty())
@@ -63,7 +64,7 @@
return;
}
- vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
+ std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
for (; it != nextSteps.end(); it++)
m_face.expressInterest((*it)->m_interest,
@@ -87,7 +88,7 @@
const OnDataValidationFailed& onValidationFailed,
int nSteps)
{
- vector<shared_ptr<ValidationRequest> > nextSteps;
+ std::vector<shared_ptr<ValidationRequest> > nextSteps;
checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
if (!nextSteps.empty())
@@ -98,7 +99,7 @@
"Require more information to validate the data!");
}
- vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
+ std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
for (; it != nextSteps.end(); it++)
m_face.expressInterest((*it)->m_interest,
@@ -147,13 +148,25 @@
{
switch (data.getSignature().getType())
{
- case Signature::Sha256WithRsa:
+ case Tlv::SignatureSha256WithRsa:
{
SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
- return verifySignature(data, sigSha256Rsa, key);
+ return verifySignature(data.wireEncode().value(),
+ data.wireEncode().value_size() -
+ data.getSignature().getValue().size(),
+ sigSha256Rsa, key);
}
+ case Tlv::SignatureSha256WithEcdsa:
+ {
+ SignatureSha256WithEcdsa sigSha256Ecdsa(data.getSignature());
+ return verifySignature(data.wireEncode().value(),
+ data.wireEncode().value_size() -
+ data.getSignature().getValue().size(),
+ sigSha256Ecdsa, key);
+ }
default:
{
+ // Unsupported sig type
return false;
}
}
@@ -182,7 +195,7 @@
switch (sig.getType())
{
- case Signature::Sha256WithRsa:
+ case Tlv::SignatureSha256WithRsa:
{
SignatureSha256WithRsa sigSha256Rsa(sig);
@@ -190,8 +203,17 @@
nameBlock.value_size() - interestName[-1].size(),
sigSha256Rsa, key);
}
+ case Tlv::SignatureSha256WithEcdsa:
+ {
+ SignatureSha256WithEcdsa sigSha256Ecdsa(sig);
+
+ return verifySignature(nameBlock.value(),
+ nameBlock.value_size() - interestName[-1].size(),
+ sigSha256Ecdsa, key);
+ }
default:
{
+ // Unsupported sig type
return false;
}
}
@@ -208,50 +230,94 @@
}
bool
-Validator::verifySignature(const Buffer& data, const Signature& sig, const PublicKey& key)
-{
- try
- {
- switch (sig.getType())
- {
- case Signature::Sha256WithRsa:
- {
- SignatureSha256WithRsa sigSha256Rsa(sig);
- return verifySignature(data, sigSha256Rsa, key);
- }
- default:
- {
- return false;
- }
- }
- }
- catch (Signature::Error& e)
- {
- return false;
- }
- return false;
-}
-
-bool
Validator::verifySignature(const uint8_t* buf,
const size_t size,
- const SignatureSha256WithRsa& sig,
+ const SignatureWithPublicKey& sig,
const PublicKey& key)
{
try
{
using namespace CryptoPP;
- RSA::PublicKey publicKey;
- ByteQueue queue;
+ switch (sig.getType())
+ {
+ case Tlv::SignatureSha256WithRsa:
+ {
+ if (key.getKeyType() != KEY_TYPE_RSA)
+ return false;
- queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
- publicKey.Load(queue);
+ RSA::PublicKey publicKey;
+ ByteQueue queue;
- RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
- return verifier.VerifyMessage(buf, size,
- sig.getValue().value(),
- sig.getValue().value_size());
+ queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
+ publicKey.Load(queue);
+
+ RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
+ return verifier.VerifyMessage(buf, size,
+ sig.getValue().value(), sig.getValue().value_size());
+ }
+ case Tlv::SignatureSha256WithEcdsa:
+ {
+ if (key.getKeyType() != KEY_TYPE_ECDSA)
+ return false;
+
+ ECDSA<ECP, SHA256>::PublicKey publicKey;
+ ByteQueue queue;
+
+ queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
+ publicKey.Load(queue);
+
+ ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+
+ uint32_t length = 0;
+ StringSource src(key.get().buf(), key.get().size(), true);
+ BERSequenceDecoder subjectPublicKeyInfo(src);
+ {
+ BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
+ {
+ OID algorithm;
+ algorithm.decode(algorithmInfo);
+
+ OID curveId;
+ curveId.decode(algorithmInfo);
+
+ if (curveId == SECP256R1)
+ length = 256;
+ else if (curveId == SECP384R1)
+ length = 384;
+ else
+ return false;
+ }
+ }
+
+ switch (length)
+ {
+ case 256:
+ {
+ uint8_t buffer[64];
+ size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+ sig.getValue().value(),
+ sig.getValue().value_size(),
+ DSA_DER);
+ return verifier.VerifyMessage(buf, size, buffer, usedSize);
+ }
+ case 384:
+ {
+ uint8_t buffer[96];
+ size_t usedSize = DSAConvertSignatureFormat(buffer, 96, DSA_P1363,
+ sig.getValue().value(),
+ sig.getValue().value_size(),
+ DSA_DER);
+ return verifier.VerifyMessage(buf, size, buffer, usedSize);
+ }
+ default:
+ return false;
+ }
+ }
+ default:
+ // Unsupported sig type
+ return false;
+ }
}
catch (CryptoPP::Exception& e)
{
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index 5d66367..87c2bfd 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -31,6 +31,7 @@
#include "../face.hpp"
#include "public-key.hpp"
#include "signature-sha256-with-rsa.hpp"
+#include "signature-sha256-with-ecdsa.hpp"
#include "digest-sha256.hpp"
#include "validation-request.hpp"
@@ -106,12 +107,15 @@
/// @brief Verify the blob using the publicKey against the signature.
static bool
- verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey);
+ verifySignature(const Buffer& blob, const SignatureWithPublicKey& sig, const PublicKey& publicKey)
+ {
+ return verifySignature(blob.buf(), blob.size(), sig, publicKey);
+ }
/// @brief Verify the data using the publicKey against the SHA256-RSA signature.
static bool
verifySignature(const Data& data,
- const SignatureSha256WithRsa& sig,
+ const SignatureWithPublicKey& sig,
const PublicKey& publicKey)
{
return verifySignature(data.wireEncode().value(),
@@ -125,7 +129,7 @@
*/
static bool
verifySignature(const Interest& interest,
- const SignatureSha256WithRsa& sig,
+ const SignatureWithPublicKey& sig,
const PublicKey& publicKey)
{
if (interest.getName().size() < 2)
@@ -140,18 +144,9 @@
/// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
static bool
- verifySignature(const Buffer& blob,
- const SignatureSha256WithRsa& sig,
- const PublicKey& publicKey)
- {
- return verifySignature(blob.buf(), blob.size(), sig, publicKey);
- }
-
- /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
- static bool
verifySignature(const uint8_t* buf,
const size_t size,
- const SignatureSha256WithRsa& sig,
+ const SignatureWithPublicKey& sig,
const PublicKey& publicKey);
diff --git a/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp b/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp
index 547eac0..6d44811 100644
--- a/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp
+++ b/tests/unit-tests/security/test-sec-public-info-sqlite3.cpp
@@ -121,11 +121,13 @@
shared_ptr<PublicKey> rsaKey;
BOOST_REQUIRE_NO_THROW(rsaKey = shared_ptr<PublicKey>(new PublicKey(os.buf()->buf(),
os.buf()->size())));
- Name rsaKeyName("/TestSecPublicInfoSqlite3/KeyType/RSA");
+ Name rsaKeyName("/TestSecPublicInfoSqlite3/KeyType/RSA/ksk-123");
SecPublicInfoSqlite3 pib;
pib.addPublicKey(rsaKeyName, rsaKey->getKeyType(), *rsaKey);
BOOST_CHECK_EQUAL(KEY_TYPE_RSA, pib.getPublicKeyType(rsaKeyName));
+
+ pib.deleteIdentityInfo(Name("/TestSecPublicInfoSqlite3/KeyType/RSA"));
}
BOOST_AUTO_TEST_CASE(KeyTypeEcdsa)
@@ -139,12 +141,12 @@
shared_ptr<PublicKey> ecdsaKey;
BOOST_REQUIRE_NO_THROW(ecdsaKey = shared_ptr<PublicKey>(new PublicKey(os.buf()->buf(),
os.buf()->size())));
- Name ecdsaKeyName("/TestSecPublicInfoSqlite3/KeyType/ECDSA");
+ Name ecdsaKeyName("/TestSecPublicInfoSqlite3/KeyType/ECDSA/ksk-123");
SecPublicInfoSqlite3 pib;
pib.addPublicKey(ecdsaKeyName, ecdsaKey->getKeyType(), *ecdsaKey);
BOOST_CHECK_EQUAL(KEY_TYPE_ECDSA, pib.getPublicKeyType(ecdsaKeyName));
-
+ pib.deleteIdentityInfo(Name("/TestSecPublicInfoSqlite3/KeyType/ECDSA"));
}
BOOST_AUTO_TEST_CASE(KeyTypeNonExist)
diff --git a/tests/unit-tests/security/test-sec-tpm-file.cpp b/tests/unit-tests/security/test-sec-tpm-file.cpp
index bcfcec0..c25a40b 100644
--- a/tests/unit-tests/security/test-sec-tpm-file.cpp
+++ b/tests/unit-tests/security/test-sec-tpm-file.cpp
@@ -243,6 +243,52 @@
BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
}
+BOOST_AUTO_TEST_CASE(EcdsaSigning)
+{
+ SecTpmFile tpm;
+
+ Name keyName("/TestSecTpmFile/EcdsaSigning/ksk-" +
+ boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+ EcdsaKeyParams params;
+ BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+ Data data("/TestSecTpmFile/EcdsaSigning/Data/1");
+ const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+ Block sigBlock;
+ BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+ keyName, DIGEST_ALGORITHM_SHA256));
+
+ shared_ptr<PublicKey> pubkeyPtr;
+ BOOST_CHECK_NO_THROW(pubkeyPtr = tpm.getPublicKeyFromTpm(keyName));
+
+ try
+ {
+ using namespace CryptoPP;
+
+ ECDSA<ECP, SHA256>::PublicKey publicKey;
+ ByteQueue queue;
+ queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+ publicKey.Load(queue);
+
+ uint8_t buffer[64];
+ size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+ sigBlock.value(), sigBlock.value_size(), DSA_DER);
+
+ ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+ bool result = verifier.VerifyMessage(content, sizeof(content),
+ buffer, usedSize);
+
+ BOOST_CHECK_EQUAL(result, true);
+ }
+ catch (CryptoPP::Exception& e)
+ {
+ BOOST_CHECK(false);
+ }
+
+ tpm.deleteKeyPairInTpm(keyName);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace ndn
diff --git a/tests/unit-tests/security/test-sec-tpm-osx.cpp b/tests/unit-tests/security/test-sec-tpm-osx.cpp
index da92cc9..3b28c66 100644
--- a/tests/unit-tests/security/test-sec-tpm-osx.cpp
+++ b/tests/unit-tests/security/test-sec-tpm-osx.cpp
@@ -200,6 +200,51 @@
SecTpmOsx::Error);
}
+BOOST_AUTO_TEST_CASE(EcdsaSigning)
+{
+ SecTpmOsx tpm;
+
+ Name keyName("/TestSecTpmOsx/EcdsaSigning/ksk-" +
+ boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
+ EcdsaKeyParams params;
+ BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
+
+ Data data("/TestSecTpmOsx/EcdsaSigning/Data/1");
+ const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+
+ Block sigBlock;
+ BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
+ keyName, DIGEST_ALGORITHM_SHA256));
+
+ shared_ptr<PublicKey> pubkeyPtr;
+ BOOST_CHECK_NO_THROW(pubkeyPtr = tpm.getPublicKeyFromTpm(keyName));
+
+ try
+ {
+ using namespace CryptoPP;
+
+ ECDSA<ECP, SHA256>::PublicKey publicKey;
+ ByteQueue queue;
+ queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+ publicKey.Load(queue);
+
+ uint8_t buffer[64];
+ size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
+ sigBlock.value(), sigBlock.value_size(), DSA_DER);
+
+ ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
+ bool result = verifier.VerifyMessage(content, sizeof(content),
+ buffer, usedSize);
+
+ BOOST_CHECK_EQUAL(result, true);
+ }
+ catch (CryptoPP::Exception& e)
+ {
+ BOOST_CHECK(false);
+ }
+
+ tpm.deleteKeyPairInTpm(keyName);
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/unit-tests/security/test-validator.cpp b/tests/unit-tests/security/test-validator.cpp
index b8d6157..bd91280 100644
--- a/tests/unit-tests/security/test-validator.cpp
+++ b/tests/unit-tests/security/test-validator.cpp
@@ -69,6 +69,141 @@
keyChain.deleteIdentity(identity);
}
+const uint8_t ecdsaSigInfo[] = {
+0x16, 0x1b, // SignatureInfo
+ 0x1b, 0x01, // SignatureType
+ 0x03,
+ 0x1c, 0x16, // KeyLocator
+ 0x07, 0x14, // Name
+ 0x08, 0x04,
+ 0x74, 0x65, 0x73, 0x74,
+ 0x08, 0x03,
+ 0x6b, 0x65, 0x79,
+ 0x08, 0x07,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72
+};
+
+const uint8_t ecdsaSigValue[] = {
+0x17, 0x40, // SignatureValue
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+ 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+ 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+ 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+ 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b
+};
+
+BOOST_AUTO_TEST_CASE(RsaSignatureVerification)
+{
+ BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+ KeyChain keyChain("sqlite3", "file");
+
+ Name identity("/TestValidator/RsaSignatureVerification");
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+ Name keyName = keyChain.getDefaultKeyNameForIdentity(identity);
+ shared_ptr<PublicKey> publicKey = keyChain.getPublicKey(keyName);
+
+ Name identity2("/TestValidator/RsaSignatureVerification/id2");
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity2));
+ Name keyName2 = keyChain.getDefaultKeyNameForIdentity(identity2);
+ shared_ptr<PublicKey> publicKey2 = keyChain.getPublicKey(keyName2);
+
+
+ Data data("/TestData/1");
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(data, identity));
+ BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey), true);
+ BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey2), false);
+
+ Interest interest("/TestInterest/1");
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(interest, identity));
+ BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey), true);
+ BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey2), false);
+
+ Data wrongData("/TestData/2");
+ Block ecdsaSigInfoBlock(ecdsaSigInfo, sizeof(ecdsaSigInfo));
+ Block ecdsaSigValueBlock(ecdsaSigValue, sizeof(ecdsaSigValue));
+ Signature ecdsaSig(ecdsaSigInfoBlock, ecdsaSigValueBlock);
+ wrongData.setSignature(ecdsaSig);
+ BOOST_CHECK_EQUAL(Validator::verifySignature(wrongData, *publicKey), false);
+
+ keyChain.deleteIdentity(identity);
+ keyChain.deleteIdentity(identity2);
+}
+
+const uint8_t rsaSigInfo[] = {
+0x16, 0x1b, // SignatureInfo
+ 0x1b, 0x01, // SignatureType
+ 0x01,
+ 0x1c, 0x16, // KeyLocator
+ 0x07, 0x14, // Name
+ 0x08, 0x04,
+ 0x74, 0x65, 0x73, 0x74,
+ 0x08, 0x03,
+ 0x6b, 0x65, 0x79,
+ 0x08, 0x07,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72
+};
+
+const uint8_t rsaSigValue[] = {
+0x17, 0x80, // SignatureValue
+ 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+ 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+ 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+ 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+ 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
+ 0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
+ 0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
+ 0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
+ 0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
+ 0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
+};
+
+
+BOOST_AUTO_TEST_CASE(EcdsaSignatureVerification)
+{
+ BOOST_REQUIRE_NO_THROW(KeyChain("sqlite3", "file"));
+ KeyChain keyChain("sqlite3", "file");
+
+ Name identity("/TestValidator/EcdsaSignatureVerification");
+ EcdsaKeyParams params;
+ // BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity, params));
+ try
+ {
+ keyChain.createIdentity(identity, params);
+ }
+ catch (std::runtime_error& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ Name keyName = keyChain.getDefaultKeyNameForIdentity(identity);
+ shared_ptr<PublicKey> publicKey = keyChain.getPublicKey(keyName);
+
+ Name identity2("/TestValidator/EcdsaSignatureVerification/id2");
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity2, params));
+ Name keyName2 = keyChain.getDefaultKeyNameForIdentity(identity2);
+ shared_ptr<PublicKey> publicKey2 = keyChain.getPublicKey(keyName2);
+
+
+ Data data("/TestData/1");
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(data, identity));
+ BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey), true);
+ BOOST_CHECK_EQUAL(Validator::verifySignature(data, *publicKey2), false);
+
+ Interest interest("/TestInterest/1");
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(interest, identity));
+ BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey), true);
+ BOOST_CHECK_EQUAL(Validator::verifySignature(interest, *publicKey2), false);
+
+ Data wrongData("/TestData/2");
+ Block rsaSigInfoBlock(rsaSigInfo, sizeof(rsaSigInfo));
+ Block rsaSigValueBlock(rsaSigValue, sizeof(rsaSigValue));
+ Signature rsaSig(rsaSigInfoBlock, rsaSigValueBlock);
+ wrongData.setSignature(rsaSig);
+ BOOST_CHECK_EQUAL(Validator::verifySignature(wrongData, *publicKey), false);
+
+ keyChain.deleteIdentity(identity);
+ keyChain.deleteIdentity(identity2);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace ndn