aboutsummaryrefslogtreecommitdiffstats
path: root/libtransport/src/auth
diff options
context:
space:
mode:
authorMauro <you@example.com>2021-06-30 07:57:22 +0000
committerMauro Sardara <msardara@cisco.com>2021-07-06 16:16:04 +0000
commit08233d44a6cfde878d7e10bca38ae935ed1c8fd5 (patch)
tree7ecc534d55bdc7e8dd15ecab084720910bcdf4d9 /libtransport/src/auth
parent147ba39bed26887f5eba84757e2463ab8e370a9a (diff)
[HICN-713] Transport Library Major Refactoring 2
Co-authored-by: Luca Muscariello <muscariello@ieee.org> Co-authored-by: Michele Papalini <micpapal@cisco.com> Co-authored-by: Olivier Roques <oroques+fdio@cisco.com> Co-authored-by: Giulio Grassi <gigrassi@cisco.com> Signed-off-by: Mauro Sardara <msardara@cisco.com> Change-Id: I5b2c667bad66feb45abdb5effe22ed0f6c85d1c2
Diffstat (limited to 'libtransport/src/auth')
-rw-r--r--libtransport/src/auth/CMakeLists.txt4
-rw-r--r--libtransport/src/auth/crypto_hash.cc201
-rw-r--r--libtransport/src/auth/crypto_suite.cc81
-rw-r--r--libtransport/src/auth/identity.cc286
-rw-r--r--libtransport/src/auth/signer.cc277
-rw-r--r--libtransport/src/auth/verifier.cc427
6 files changed, 901 insertions, 375 deletions
diff --git a/libtransport/src/auth/CMakeLists.txt b/libtransport/src/auth/CMakeLists.txt
index 0e7b5832b..699bc1050 100644
--- a/libtransport/src/auth/CMakeLists.txt
+++ b/libtransport/src/auth/CMakeLists.txt
@@ -11,12 +11,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/signer.cc
${CMAKE_CURRENT_SOURCE_DIR}/verifier.cc
${CMAKE_CURRENT_SOURCE_DIR}/identity.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.cc
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/auth/crypto_hash.cc b/libtransport/src/auth/crypto_hash.cc
new file mode 100644
index 000000000..b4b0a8b81
--- /dev/null
+++ b/libtransport/src/auth/crypto_hash.cc
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/auth/crypto_hash.h>
+
+using namespace std;
+
+namespace transport {
+namespace auth {
+
+CryptoHash::CryptoHash() : CryptoHash(CryptoHashType::UNKNOWN) {}
+
+CryptoHash::CryptoHash(const CryptoHash &other)
+ : digest_type_(other.digest_type_),
+ digest_(other.digest_),
+ digest_size_(other.digest_size_) {}
+
+CryptoHash::CryptoHash(CryptoHash &&other)
+ : digest_type_(move(other.digest_type_)),
+ digest_(other.digest_),
+ digest_size_(other.digest_size_) {
+ other.reset();
+}
+
+CryptoHash::CryptoHash(CryptoHashType hash_type) { setType(hash_type); }
+
+CryptoHash::CryptoHash(const uint8_t *hash, size_t size,
+ CryptoHashType hash_type)
+ : digest_type_(hash_type), digest_size_(size) {
+ digest_.resize(size);
+ memcpy(digest_.data(), hash, size);
+}
+
+CryptoHash::CryptoHash(const vector<uint8_t> &hash, CryptoHashType hash_type)
+ : CryptoHash(hash.data(), hash.size(), hash_type) {}
+
+CryptoHash &CryptoHash::operator=(const CryptoHash &other) {
+ digest_type_ = other.digest_type_;
+ digest_ = other.digest_;
+ digest_size_ = other.digest_size_;
+ return *this;
+}
+
+bool CryptoHash::operator==(const CryptoHash &other) const {
+ return (digest_type_ == other.digest_type_ && digest_ == other.digest_);
+}
+
+void CryptoHash::computeDigest(const uint8_t *buffer, size_t len) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(digest_type_);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ EVP_Digest(buffer, len, digest_.data(), (unsigned int *)&digest_size_,
+ (*hash_evp)(), nullptr);
+}
+
+void CryptoHash::computeDigest(const vector<uint8_t> &buffer) {
+ computeDigest(buffer.data(), buffer.size());
+}
+
+void CryptoHash::computeDigest(const utils::MemBuf *buffer) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(digest_type_);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ EVP_MD_CTX *mcdtx = EVP_MD_CTX_new();
+ const utils::MemBuf *p = buffer;
+
+ if (EVP_DigestInit_ex(mcdtx, (*hash_evp)(), nullptr) == 0) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestUpdate(mcdtx, p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
+
+ p = p->next();
+ } while (p != buffer);
+
+ if (EVP_DigestFinal_ex(mcdtx, digest_.data(),
+ (unsigned int *)&digest_size_) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
+
+ EVP_MD_CTX_free(mcdtx);
+}
+
+vector<uint8_t> CryptoHash::getDigest() const { return digest_; }
+
+string CryptoHash::getStringDigest() const {
+ stringstream string_digest;
+
+ string_digest << hex << setfill('0');
+
+ for (auto byte : digest_) {
+ string_digest << hex << setw(2) << static_cast<int>(byte);
+ }
+
+ return string_digest.str();
+}
+
+CryptoHashType CryptoHash::getType() const { return digest_type_; }
+
+size_t CryptoHash::getSize() const { return digest_size_; }
+
+void CryptoHash::setType(CryptoHashType hash_type) {
+ reset();
+ digest_type_ = hash_type;
+ digest_size_ = CryptoHash::getSize(hash_type);
+ digest_.resize(digest_size_);
+}
+
+void CryptoHash::display() {
+ switch (digest_type_) {
+ case CryptoHashType::SHA256:
+ cout << "SHA256";
+ break;
+ case CryptoHashType::SHA512:
+ cout << "SHA512";
+ break;
+ case CryptoHashType::BLAKE2S256:
+ cout << "BLAKE2s256";
+ break;
+ case CryptoHashType::BLAKE2B512:
+ cout << "BLAKE2b512";
+ break;
+ default:
+ cout << "UNKNOWN";
+ break;
+ }
+
+ cout << ": " << getStringDigest() << endl;
+}
+
+void CryptoHash::reset() {
+ digest_type_ = CryptoHashType::UNKNOWN;
+ digest_.clear();
+ digest_size_ = 0;
+}
+
+CryptoHashEVP CryptoHash::getEVP(CryptoHashType hash_type) {
+ switch (hash_type) {
+ case CryptoHashType::SHA256:
+ return &EVP_sha256;
+ break;
+ case CryptoHashType::SHA512:
+ return &EVP_sha512;
+ break;
+ case CryptoHashType::BLAKE2S256:
+ return &EVP_blake2s256;
+ break;
+ case CryptoHashType::BLAKE2B512:
+ return &EVP_blake2b512;
+ break;
+ default:
+ return nullptr;
+ break;
+ }
+}
+
+size_t CryptoHash::getSize(CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ return 0;
+ }
+
+ return EVP_MD_size((*hash_evp)());
+}
+
+bool CryptoHash::compareDigest(const uint8_t *digest1, const uint8_t *digest2,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ return false;
+ }
+
+ return !static_cast<bool>(
+ memcmp(digest1, digest2, CryptoHash::getSize(hash_type)));
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/auth/crypto_suite.cc b/libtransport/src/auth/crypto_suite.cc
new file mode 100644
index 000000000..7e898ef09
--- /dev/null
+++ b/libtransport/src/auth/crypto_suite.cc
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/auth/crypto_suite.h>
+
+namespace transport {
+namespace auth {
+
+CryptoSuite getSuite(int nid) {
+ switch (nid) {
+ case NID_ecdsa_with_SHA256:
+ return CryptoSuite::ECDSA_SHA256;
+ break;
+ case NID_ecdsa_with_SHA512:
+ return CryptoSuite::ECDSA_SHA512;
+ break;
+ case NID_sha256WithRSAEncryption:
+ return CryptoSuite::RSA_SHA256;
+ break;
+ case NID_sha512WithRSAEncryption:
+ return CryptoSuite::RSA_SHA512;
+ break;
+ case NID_hmacWithSHA256:
+ return CryptoSuite::HMAC_SHA256;
+ break;
+ case NID_hmacWithSHA512:
+ return CryptoSuite::HMAC_SHA512;
+ break;
+ case NID_dsa_with_SHA256:
+ return CryptoSuite::DSA_SHA256;
+ break;
+ case NID_dsa_with_SHA512:
+ return CryptoSuite::DSA_SHA512;
+ break;
+ default:
+ return CryptoSuite::UNKNOWN;
+ break;
+ }
+}
+
+CryptoHashType getHashType(CryptoSuite suite) {
+ switch (suite) {
+ case CryptoSuite::ECDSA_BLAKE2B512:
+ case CryptoSuite::RSA_BLAKE2B512:
+ case CryptoSuite::HMAC_BLAKE2B512:
+ case CryptoSuite::DSA_BLAKE2B512:
+ return CryptoHashType::BLAKE2B512;
+ case CryptoSuite::ECDSA_BLAKE2S256:
+ case CryptoSuite::RSA_BLAKE2S256:
+ case CryptoSuite::HMAC_BLAKE2S256:
+ case CryptoSuite::DSA_BLAKE2S256:
+ return CryptoHashType::BLAKE2S256;
+ case CryptoSuite::ECDSA_SHA256:
+ case CryptoSuite::RSA_SHA256:
+ case CryptoSuite::HMAC_SHA256:
+ case CryptoSuite::DSA_SHA256:
+ return CryptoHashType::SHA256;
+ case CryptoSuite::ECDSA_SHA512:
+ case CryptoSuite::RSA_SHA512:
+ case CryptoSuite::HMAC_SHA512:
+ case CryptoSuite::DSA_SHA512:
+ return CryptoHashType::SHA512;
+ default:
+ return CryptoHashType::UNKNOWN;
+ }
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/auth/identity.cc b/libtransport/src/auth/identity.cc
index bd787b9b6..f56532033 100644
--- a/libtransport/src/auth/identity.cc
+++ b/libtransport/src/auth/identity.cc
@@ -17,90 +17,262 @@
using namespace std;
+// function needed to create the a certificate
+static bool _addRandomSerial(X509 *cert) {
+ unsigned long serial = 0;
+ unsigned char serial_bytes[sizeof(serial)];
+
+ // Construct random positive serial number.
+ RAND_bytes(serial_bytes, sizeof(serial_bytes));
+ serial_bytes[0] &= 0x7F;
+ serial = 0;
+ for (size_t i = 0; i < sizeof(serial_bytes); i++) {
+ serial = (256 * serial) + serial_bytes[i];
+ }
+ ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
+ return true;
+}
+
+static bool _addValidityPeriod(X509 *cert, size_t validityDays) {
+ // Set the validity from now for the specified number of days.
+ X509_gmtime_adj(X509_get_notBefore(cert), (long)0);
+ X509_gmtime_adj(X509_get_notAfter(cert), (long)(60 * 60 * 24 * validityDays));
+ return true;
+}
+
+static bool _addSubjectName(X509 *cert, const char *subjectname) {
+ // Set up the simple subject name and issuer name for the certificate.
+ X509_NAME *name = X509_get_subject_name(cert);
+
+ if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
+ (unsigned char *)subjectname, -1, -1, 0)) {
+ if (X509_set_issuer_name(cert, name)) {
+ return true;
+ }
+ }
+ return false;
+}
+static bool _addCertificateExtensionWithContext(X509 *cert, int nid,
+ const char *value) {
+ X509_EXTENSION *extension;
+ X509V3_CTX context;
+
+ X509V3_set_ctx_nodb(&context);
+ X509V3_set_ctx(&context, cert, cert, NULL, NULL, 0);
+ extension = X509V3_EXT_conf_nid(NULL, &context, nid, value);
+ if (extension == NULL) {
+ return false;
+ }
+ X509_add_ext(cert, extension, -1);
+ X509_EXTENSION_free(extension);
+ return true;
+}
+static bool _addCertificateExtension(X509 *cert, int nid, const char *value) {
+ X509_EXTENSION *extension = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
+ if (extension == NULL) {
+ return false;
+ }
+ X509_add_ext(cert, extension, -1);
+ X509_EXTENSION_free(extension);
+ return true;
+}
+
+static bool _addExtensions(X509 *cert) {
+ // Add the necessary extensions.
+ if (_addCertificateExtension(cert, NID_basic_constraints,
+ "critical,CA:FALSE") == true) {
+ if (_addCertificateExtension(
+ cert, NID_key_usage,
+ "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,"
+ "keyAgreement") == true) {
+ if (_addCertificateExtension(cert, NID_ext_key_usage, "clientAuth") ==
+ true) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+static bool _addKeyIdentifier(X509 *cert) {
+ unsigned char spkid[SHA256_DIGEST_LENGTH];
+ char spkid_hex[1 + 2 * SHA256_DIGEST_LENGTH];
+ if (ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(),
+ X509_get_X509_PUBKEY(cert), spkid, NULL)) {
+ for (int i = 0; i < 32; i++) {
+ snprintf(&spkid_hex[2 * i], 3, "%02X", (unsigned)spkid[i]);
+ }
+ if (_addCertificateExtension(cert, NID_subject_key_identifier, spkid_hex) ==
+ true) {
+ if (_addCertificateExtensionWithContext(
+ cert, NID_authority_key_identifier, "keyid:always") == true) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
namespace transport {
namespace auth {
Identity::Identity(const string &keystore_path, const string &keystore_pwd,
CryptoSuite suite, unsigned int signature_len,
unsigned int validity_days, const string &subject_name)
- : identity_(nullptr), signer_(nullptr) {
- parcSecurity_Init();
-
- bool success = parcPkcs12KeyStore_CreateFile(
- keystore_path.c_str(), keystore_pwd.c_str(), subject_name.c_str(),
- parcCryptoSuite_GetSigningAlgorithm(static_cast<PARCCryptoSuite>(suite)),
- signature_len, validity_days);
+ : cert_(X509_new(), ::X509_free) {
+ // create the file and complete it.
+ // first we create the certificate
- parcAssertTrue(
- success,
- "parcPkcs12KeyStore_CreateFile('%s', '%s', '%s', %d, %d, %d) failed.",
- keystore_path.c_str(), keystore_pwd.c_str(), subject_name.c_str(),
- static_cast<int>(suite), static_cast<int>(signature_len), validity_days);
+ // to create the cert we will need a private key
- PARCIdentityFile *identity_file =
- parcIdentityFile_Create(keystore_path.c_str(), keystore_pwd.c_str());
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
- identity_ =
- parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
+ if (suite == CryptoSuite::RSA_SHA512 || suite == CryptoSuite::RSA_SHA256) {
+ RSA *rsa = RSA_new();
+ BIGNUM *pub_exp;
- PARCSigner *signer = parcIdentity_CreateSigner(
- identity_,
- parcCryptoSuite_GetCryptoHash(static_cast<PARCCryptoSuite>(suite)));
+ pub_exp = BN_new();
- signer_ = make_shared<AsymmetricSigner>(signer);
-
- parcSigner_Release(&signer);
- parcIdentityFile_Release(&identity_file);
+ BN_set_word(pub_exp, RSA_F4);
+ if (1 != RSA_generate_key_ex(rsa, signature_len, pub_exp, NULL))
+ throw errors::RuntimeException("can't generate the key");
+ if (1 != EVP_PKEY_set1_RSA(privateKey.get(), rsa))
+ throw errors::RuntimeException("can't generate the key");
+ } else if (suite == CryptoSuite::ECDSA_SHA256) {
+ int curve_params;
+ switch (signature_len) {
+ case 160u:
+ curve_params = NID_secp160k1;
+ break;
+ case 192u:
+ curve_params = NID_secp192k1;
+ break;
+ case 224u:
+ curve_params = NID_secp224k1;
+ break;
+ case 256u:
+ curve_params = NID_secp256k1;
+ break;
+ default:
+ curve_params = -1;
+ break;
+ }
+ if (curve_params == -1)
+ throw errors::RuntimeException("can't generate the key");
+ EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve_params);
+ if (ec_key == NULL)
+ throw errors::RuntimeException("can't create ecdsa key from curve");
+ EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_generate_key(ec_key) == 0)
+ throw errors::RuntimeException("can't generate the ecdsa key");
+ if (EVP_PKEY_set1_EC_KEY(privateKey.get(), ec_key) == 0)
+ throw errors::RuntimeException("can't generate the ecdsa key");
+ } else if (suite == CryptoSuite::DSA_SHA256) {
+ DSA *dsa = DSA_new();
+ unsigned char buffer[32];
+ if (RAND_bytes(buffer, sizeof(buffer)) != 1) {
+ throw errors::RuntimeException("can't generate the key");
+ }
+ if (DSA_generate_parameters_ex(dsa, signature_len, buffer, sizeof(buffer),
+ NULL, NULL, NULL) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (DSA_generate_key(dsa) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (EVP_PKEY_set1_DSA(privateKey.get(), dsa) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ }
+ bool success = true;
+ success = success && (X509_set_version(cert_.get(), 2) == 1); // 2 => X509v3
+ success = success && _addRandomSerial(cert_.get());
+ success = success && _addValidityPeriod(cert_.get(), validity_days);
+ success = success && (X509_set_pubkey(cert_.get(), privateKey.get()) == 1);
+ success = success && _addSubjectName(cert_.get(), subject_name.c_str());
+ success = success && _addExtensions(cert_.get());
+ success =
+ success && (X509_sign(cert_.get(), privateKey.get(), EVP_sha256()) != 0);
+ success = success && _addKeyIdentifier(cert_.get());
+ if (!success) {
+ throw errors::RuntimeException("error while creating the certificate");
+ }
+ // the certificate is created. We create the pkcs12 object to write the p12
+ // file
+ PKCS12 *p12 = PKCS12_create(
+ keystore_pwd.c_str(), "ccnxuser", privateKey.get(), cert_.get(), NULL, 0,
+ 0, 0 /*default iter*/, PKCS12_DEFAULT_ITER /*mac_iter*/, 0);
+ filename_ = keystore_path;
+ int fp = open(filename_.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0600);
+ if (fp == -1) throw errors::RuntimeException("impossible to create the file");
+ FILE *fp_f = fdopen(fp, "wb");
+ if (fp_f == NULL)
+ throw errors::RuntimeException("impossible to create the file");
+ i2d_PKCS12_fp(fp_f, p12);
+ fclose(fp_f);
+ close(fp);
+ std::shared_ptr<EVP_PKEY> publickey(X509_get_pubkey(cert_.get()),
+ EVP_PKEY_free);
+ signer_ = std::shared_ptr<AsymmetricSigner>(
+ new AsymmetricSigner(suite, privateKey, publickey));
+ signer_->signature_len_ = signature_len;
}
Identity::Identity(string &keystore_path, string &keystore_pwd,
CryptoHashType hash_type)
- : identity_(nullptr), signer_(nullptr) {
- parcSecurity_Init();
-
- PARCIdentityFile *identity_file =
- parcIdentityFile_Create(keystore_path.c_str(), keystore_pwd.c_str());
-
- identity_ =
- parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
-
- PARCSigner *signer = parcIdentity_CreateSigner(
- identity_, static_cast<PARCCryptoHashType>(hash_type));
-
- signer_ = make_shared<AsymmetricSigner>(signer);
-
- parcSigner_Release(&signer);
- parcIdentityFile_Release(&identity_file);
+ : cert_(X509_new(), ::X509_free) {
+ filename_ = keystore_path;
+ pwd_ = keystore_path;
+ // get the key and certificate by first opening the keystore file
+ FILE *p12file = fopen(keystore_path.c_str(), "r");
+ if (p12file == NULL)
+ throw errors::RuntimeException("impossible open keystore");
+ PKCS12 *p12 = d2i_PKCS12_fp(p12file, NULL);
+ EVP_PKEY *privatekey;
+ EVP_PKEY *publickey;
+ X509 *cert = cert_.get();
+ // now we parse the file to get the first key and certificate
+ if (1 != PKCS12_parse(p12, keystore_pwd.c_str(), &privatekey, &cert, NULL))
+ throw errors::RuntimeException("impossible to get the private key");
+ publickey = X509_get_pubkey(cert);
+ // to have the cryptosuite we use the nid number that is used to identify the
+ // suite.
+ CryptoSuite suite = getSuite(X509_get_signature_nid(cert));
+ signer_ = std::shared_ptr<AsymmetricSigner>(new AsymmetricSigner(
+ suite, std::shared_ptr<EVP_PKEY>(privatekey, EVP_PKEY_free),
+ std::shared_ptr<EVP_PKEY>(publickey, EVP_PKEY_free)));
+ PKCS12_free(p12);
}
-Identity::Identity(const Identity &other)
- : identity_(nullptr), signer_(other.signer_) {
- parcSecurity_Init();
- identity_ = parcIdentity_Acquire(other.identity_);
+Identity::Identity(const Identity &other) {
+ pwd_ = other.pwd_;
+ filename_ = other.filename_;
+ signer_ = other.signer_;
+ cert_ = other.cert_;
}
-Identity::Identity(Identity &&other)
- : identity_(nullptr), signer_(move(other.signer_)) {
- parcSecurity_Init();
- identity_ = parcIdentity_Acquire(other.identity_);
- parcIdentity_Release(&other.identity_);
+Identity::Identity(Identity &&other) {
+ signer_ = std::move(other.signer_);
+ other.signer_.reset();
+ cert_ = std::move(other.cert_);
+ other.cert_.reset();
+ pwd_ = other.pwd_;
+ other.pwd_ = "";
+ filename_ = other.filename_;
+ other.filename_ = "";
+ signer_ = other.signer_;
+ other.signer_ = nullptr;
}
-Identity::~Identity() {
- if (identity_) parcIdentity_Release(&identity_);
- parcSecurity_Fini();
-}
+Identity::~Identity() {}
shared_ptr<AsymmetricSigner> Identity::getSigner() const { return signer_; }
-string Identity::getFilename() const {
- return string(parcIdentity_GetFileName(identity_));
-}
+string Identity::getFilename() const { return filename_; }
-string Identity::getPassword() const {
- return string(parcIdentity_GetPassWord(identity_));
+std::shared_ptr<X509> Identity::getCertificate() const { return cert_; }
+std::shared_ptr<EVP_PKEY> Identity::getPrivateKey() const {
+ return signer_->key_;
}
+string Identity::getPassword() const { return pwd_; }
+
Identity Identity::generateIdentity(const string &subject_name) {
string keystore_name = "keystore";
string keystore_password = "password";
diff --git a/libtransport/src/auth/signer.cc b/libtransport/src/auth/signer.cc
index 99c3d099d..884e850ca 100644
--- a/libtransport/src/auth/signer.cc
+++ b/libtransport/src/auth/signer.cc
@@ -15,193 +15,214 @@
#include <hicn/transport/auth/signer.h>
-extern "C" {
-#ifndef _WIN32
-TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
-#endif
-#include <hicn/hicn.h>
-}
-
-#include <chrono>
-
-#define ALLOW_UNALIGNED_READS 1
-
using namespace std;
namespace transport {
namespace auth {
-Signer::Signer() : signer_(nullptr), key_id_(nullptr) { parcSecurity_Init(); }
+// ---------------------------------------------------------
+// Base Signer
+// ---------------------------------------------------------
+Signer::Signer()
+ : suite_(CryptoSuite::UNKNOWN), signature_len_(0), key_(nullptr) {}
-Signer::Signer(PARCSigner *signer) : Signer() { setSigner(signer); }
-
-Signer::~Signer() {
- if (signer_) parcSigner_Release(&signer_);
- if (key_id_) parcKeyId_Release(&key_id_);
- parcSecurity_Fini();
-}
+Signer::~Signer() {}
void Signer::signPacket(PacketPtr packet) {
- parcAssertNotNull(signer_, "Expected non-null signer");
-
- const utils::MemBuf &header_chain = *packet;
+ assert(key_ != nullptr);
core::Packet::Format format = packet->getFormat();
- auto suite = getCryptoSuite();
- size_t signature_len = getSignatureSize();
if (!packet->authenticationHeader()) {
throw errors::MalformedAHPacketException();
}
- packet->setSignatureSize(signature_len);
+ // Set signature size
+ size_t signature_field_len = getSignatureFieldSize();
+ packet->setSignatureSize(signature_field_len);
+ packet->setSignatureSizeGap(0u);
// Copy IP+TCP / ICMP header before zeroing them
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
- packet->resetForHash();
- // Fill in the HICN_AH header
+ // Fill in the hICN AH header
auto now = chrono::duration_cast<chrono::milliseconds>(
chrono::system_clock::now().time_since_epoch())
.count();
packet->setSignatureTimestamp(now);
- packet->setValidationAlgorithm(suite);
+ packet->setValidationAlgorithm(suite_);
- // Set the key ID
- KeyId key_id;
- key_id.first = static_cast<uint8_t *>(
- parcBuffer_Overlay((PARCBuffer *)parcKeyId_GetKeyId(key_id_), 0));
- packet->setKeyId(key_id);
+ // Set key ID
+ vector<uint8_t> key_id = key_id_.getDigest();
+ packet->setKeyId({key_id.data(), key_id.size()});
- // Calculate hash
- CryptoHasher hasher(parcSigner_GetCryptoHasher(signer_));
- const utils::MemBuf *current = &header_chain;
+ // Reset fields to compute the packet hash
+ packet->resetForHash();
- hasher.init();
+ // Compute the signature and put it in the packet
+ signBuffer(packet);
+ hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
- do {
- hasher.updateBytes(current->data(), current->length());
- current = current->next();
- } while (current != &header_chain);
+ // Set the gap between the signature field size and the signature real size.
+ packet->setSignatureSizeGap(signature_field_len - signature_len_);
+ memcpy(packet->getSignature(), signature_.data(), signature_len_);
+}
- CryptoHash hash = hasher.finalize();
+void Signer::signBuffer(const std::vector<uint8_t> &buffer) {
+ assert(key_ != nullptr);
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
- // Compute signature
- PARCSignature *signature = parcSigner_SignDigestNoAlloc(
- signer_, hash.hash_, packet->getSignature(), (uint32_t)signature_len);
- PARCBuffer *buffer = parcSignature_GetSignature(signature);
- size_t bytes_len = parcBuffer_Remaining(buffer);
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
- if (bytes_len > signature_len) {
- throw errors::MalformedAHPacketException();
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
}
- // Put signature in AH header
- hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
- // Release allocated objects
- parcSignature_Release(&signature);
-}
+ if (EVP_DigestSignUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
-void Signer::setSigner(PARCSigner *signer) {
- parcAssertNotNull(signer, "Expected non-null signer");
+ if (EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len_) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
- if (signer_) parcSigner_Release(&signer_);
- if (key_id_) parcKeyId_Release(&key_id_);
+ signature_.resize(signature_len_);
- signer_ = parcSigner_Acquire(signer);
- key_id_ = parcSigner_CreateKeyId(signer_);
-}
+ if (EVP_DigestSignFinal(mdctx.get(), signature_.data(), &signature_len_) !=
+ 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
-size_t Signer::getSignatureSize() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return parcSigner_GetSignatureSize(signer_);
+ signature_.resize(signature_len_);
}
-CryptoSuite Signer::getCryptoSuite() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return static_cast<CryptoSuite>(parcSigner_GetCryptoSuite(signer_));
-}
+void Signer::signBuffer(const utils::MemBuf *buffer) {
+ assert(key_ != nullptr);
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
-CryptoHashType Signer::getCryptoHashType() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return static_cast<CryptoHashType>(parcSigner_GetCryptoHashType(signer_));
-}
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
-PARCSigner *Signer::getParcSigner() const { return signer_; }
+ const utils::MemBuf *p = buffer;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
-PARCKeyStore *Signer::getParcKeyStore() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return parcSigner_GetKeyStore(signer_);
-}
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
+
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestSignUpdate(mdctx.get(), p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
-AsymmetricSigner::AsymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store) {
- parcAssertNotNull(key_store, "Expected non-null key_store");
+ p = p->next();
+ } while (p != buffer);
- auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
+ if (EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len_) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
+
+ signature_.resize(signature_len_);
- switch (suite) {
- case CryptoSuite::DSA_SHA256:
- case CryptoSuite::RSA_SHA256:
- case CryptoSuite::RSA_SHA512:
- case CryptoSuite::ECDSA_256K1:
- break;
- default:
- throw errors::RuntimeException(
- "Invalid crypto suite for asymmetric signer");
+ if (EVP_DigestSignFinal(mdctx.get(), signature_.data(), &signature_len_) !=
+ 1) {
+ throw errors::RuntimeException("Digest computation failed");
}
- setSigner(
- parcSigner_Create(parcPublicKeySigner_Create(key_store, crypto_suite),
- PARCPublicKeySignerAsSigner));
+ signature_.resize(signature_len_);
}
-SymmetricSigner::SymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store) {
- parcAssertNotNull(key_store, "Expected non-null key_store");
+vector<uint8_t> Signer::getSignature() const { return signature_; }
- auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
+size_t Signer::getSignatureSize() const { return signature_len_; }
- switch (suite) {
- case CryptoSuite::HMAC_SHA256:
- case CryptoSuite::HMAC_SHA512:
- break;
- default:
- throw errors::RuntimeException(
- "Invalid crypto suite for symmetric signer");
+size_t Signer::getSignatureFieldSize() const {
+ if (signature_len_ % 4 == 0) {
+ return signature_len_;
}
- setSigner(parcSigner_Create(parcSymmetricKeySigner_Create(
- (PARCSymmetricKeyStore *)key_store,
- parcCryptoSuite_GetCryptoHash(crypto_suite)),
- PARCSymmetricKeySignerAsSigner));
+ return (signature_len_ + 4) - (signature_len_ % 4);
}
-SymmetricSigner::SymmetricSigner(CryptoSuite suite, const string &passphrase) {
- auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
-
- switch (suite) {
- case CryptoSuite::HMAC_SHA256:
- case CryptoSuite::HMAC_SHA512:
- break;
- default:
- throw errors::RuntimeException(
- "Invalid crypto suite for symmetric signer");
- }
+CryptoHashType Signer::getHashType() const {
+ return ::transport::auth::getHashType(suite_);
+}
+
+CryptoSuite Signer::getSuite() const { return suite_; }
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_PutString(composer, passphrase.c_str());
- PARCBuffer *key_buf = parcBufferComposer_ProduceBuffer(composer);
- parcBufferComposer_Release(&composer);
+// ---------------------------------------------------------
+// Void Signer
+// ---------------------------------------------------------
+void VoidSigner::signPacket(PacketPtr packet){};
- PARCSymmetricKeyStore *key_store = parcSymmetricKeyStore_Create(key_buf);
- PARCSymmetricKeySigner *key_signer = parcSymmetricKeySigner_Create(
- key_store, parcCryptoSuite_GetCryptoHash(crypto_suite));
+void VoidSigner::signBuffer(const std::vector<uint8_t> &buffer){};
- setSigner(parcSigner_Create(key_signer, PARCSymmetricKeySignerAsSigner));
+void VoidSigner::signBuffer(const utils::MemBuf *buffer){};
+
+// ---------------------------------------------------------
+// Asymmetric Signer
+// ---------------------------------------------------------
+AsymmetricSigner::AsymmetricSigner(CryptoSuite suite, shared_ptr<EVP_PKEY> key,
+ shared_ptr<EVP_PKEY> pub_key) {
+ suite_ = suite;
+ key_ = key;
+ key_id_ = CryptoHash(getHashType());
+
+ vector<uint8_t> pbk(i2d_PublicKey(pub_key.get(), nullptr));
+ uint8_t *pbk_ptr = pbk.data();
+ int len = i2d_PublicKey(pub_key.get(), &pbk_ptr);
+
+ signature_len_ = EVP_PKEY_size(key.get());
+ signature_.resize(signature_len_);
+ key_id_.computeDigest(pbk_ptr, len);
+}
+
+size_t AsymmetricSigner::getSignatureFieldSize() const {
+ size_t field_size = EVP_PKEY_size(key_.get());
+
+ if (field_size % 4 == 0) {
+ return field_size;
+ }
+
+ return (field_size + 4) - (field_size % 4);
+}
+
+// ---------------------------------------------------------
+// Symmetric Signer
+// ---------------------------------------------------------
+SymmetricSigner::SymmetricSigner(CryptoSuite suite, const string &passphrase) {
+ suite_ = suite;
+ key_ = shared_ptr<EVP_PKEY>(
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, nullptr,
+ (const unsigned char *)passphrase.c_str(),
+ passphrase.size()),
+ EVP_PKEY_free);
+ key_id_ = CryptoHash(getHashType());
+
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
- parcSymmetricKeySigner_Release(&key_signer);
- parcSymmetricKeyStore_Release(&key_store);
- parcBuffer_Release(&key_buf);
+ signature_len_ = EVP_MD_size((*hash_evp)());
+ signature_.resize(signature_len_);
+ key_id_.computeDigest((uint8_t *)passphrase.c_str(), passphrase.size());
}
} // namespace auth
diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc
index c6648a763..c9ac1650f 100644
--- a/libtransport/src/auth/verifier.cc
+++ b/libtransport/src/auth/verifier.cc
@@ -16,168 +16,125 @@
#include <hicn/transport/auth/verifier.h>
#include <protocols/errors.h>
-extern "C" {
-#ifndef _WIN32
-TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
-#endif
-#include <hicn/hicn.h>
-}
-
-#include <sys/stat.h>
-
using namespace std;
namespace transport {
namespace auth {
-const std::vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = {
+const vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = {
VerificationPolicy::DROP,
VerificationPolicy::ABORT,
};
+// ---------------------------------------------------------
+// Base Verifier
+// ---------------------------------------------------------
Verifier::Verifier()
- : hasher_(nullptr),
- verifier_(nullptr),
- verification_failed_cb_(interface::VOID_HANDLER),
- failed_policies_(DEFAULT_FAILED_POLICIES) {
- parcSecurity_Init();
- PARCInMemoryVerifier *in_memory_verifier = parcInMemoryVerifier_Create();
- verifier_ =
- parcVerifier_Create(in_memory_verifier, PARCInMemoryVerifierAsVerifier);
- parcInMemoryVerifier_Release(&in_memory_verifier);
-}
+ : verification_failed_cb_(interface::VOID_HANDLER),
+ failed_policies_(DEFAULT_FAILED_POLICIES) {}
-Verifier::~Verifier() {
- if (hasher_) parcCryptoHasher_Release(&hasher_);
- if (verifier_) parcVerifier_Release(&verifier_);
- parcSecurity_Fini();
-}
+Verifier::~Verifier() {}
bool Verifier::verifyPacket(PacketPtr packet) {
- bool valid_packet = false;
core::Packet::Format format = packet->getFormat();
if (!packet->authenticationHeader()) {
throw errors::MalformedAHPacketException();
}
- // Get crypto suite and hash type
- auto suite = static_cast<PARCCryptoSuite>(packet->getValidationAlgorithm());
- PARCCryptoHashType hash_type = parcCryptoSuite_GetCryptoHash(suite);
+ // Get crypto suite, hash type, signature length
+ CryptoSuite suite = packet->getValidationAlgorithm();
+ CryptoHashType hash_type = getHashType(suite);
+ size_t signature_len = packet->getSignatureSizeReal();
// Copy IP+TCP / ICMP header before zeroing them
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
+ packet->setSignatureSizeGap(0u);
- // Fetch packet signature
+ // Retrieve packet signature
uint8_t *packet_signature = packet->getSignature();
- size_t signature_len = Verifier::getSignatureSize(packet);
vector<uint8_t> signature_raw(packet_signature,
packet_signature + signature_len);
- // Create a signature buffer from the raw packet signature
- PARCBuffer *bits =
- parcBuffer_Wrap(signature_raw.data(), signature_len, 0, signature_len);
- parcBuffer_Rewind(bits);
-
- // If the signature algo is ECDSA, the signature might be shorter than the
- // signature field
- PARCSigningAlgorithm algo = parcCryptoSuite_GetSigningAlgorithm(suite);
- if (algo == PARCSigningAlgorithm_ECDSA) {
- while (parcBuffer_HasRemaining(bits) && parcBuffer_GetUint8(bits) == 0)
- ;
- parcBuffer_SetPosition(bits, parcBuffer_Position(bits) - 1);
- }
-
- if (!parcBuffer_HasRemaining(bits)) {
- parcBuffer_Release(&bits);
- return false;
- }
-
- // Create a signature object from the signature buffer
- PARCSignature *signature = parcSignature_Create(
- parcCryptoSuite_GetSigningAlgorithm(suite), hash_type, bits);
-
- // Fetch the key to verify the signature
- KeyId key_buffer = packet->getKeyId();
- PARCBuffer *buffer = parcBuffer_Wrap(key_buffer.first, key_buffer.second, 0,
- key_buffer.second);
- PARCKeyId *key_id = parcKeyId_Create(buffer);
-
// Reset fields that are not used to compute signature
packet->resetForHash();
- // Compute the packet hash
- if (!hasher_)
- setHasher(parcVerifier_GetCryptoHasher(verifier_, key_id, hash_type));
- CryptoHash local_hash = computeHash(packet);
-
- // Compare the packet signature to the locally computed one
- valid_packet = parcVerifier_VerifyDigestSignature(
- verifier_, key_id, local_hash.hash_, suite, signature);
+ // Check signatures
+ bool valid_packet = verifyBuffer(static_cast<utils::MemBuf *>(packet),
+ signature_raw, hash_type);
- // Restore the fields that were reset
+ // Restore header
hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
-
- // Release allocated objects
- parcBuffer_Release(&buffer);
- parcKeyId_Release(&key_id);
- parcSignature_Release(&signature);
- parcBuffer_Release(&bits);
+ packet->setSignatureSizeGap(packet->getSignatureSize() - signature_len);
return valid_packet;
}
-vector<VerificationPolicy> Verifier::verifyPackets(
- const vector<PacketPtr> &packets) {
- vector<VerificationPolicy> policies(packets.size(), VerificationPolicy::DROP);
+Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets) {
+ PolicyMap policies;
+
+ for (const auto &packet : packets) {
+ Suffix suffix = packet->getName().getSuffix();
+ VerificationPolicy policy = VerificationPolicy::ABORT;
- for (unsigned int i = 0; i < packets.size(); ++i) {
- if (verifyPacket(packets[i])) {
- policies[i] = VerificationPolicy::ACCEPT;
+ if (verifyPacket(packet)) {
+ policy = VerificationPolicy::ACCEPT;
}
- callVerificationFailedCallback(packets[i], policies[i]);
+ policies[suffix] = policy;
+ callVerificationFailedCallback(packet, policy);
}
return policies;
}
-vector<VerificationPolicy> Verifier::verifyPackets(
- const vector<PacketPtr> &packets,
- const unordered_map<Suffix, HashEntry> &suffix_map) {
- vector<VerificationPolicy> policies(packets.size(),
- VerificationPolicy::UNKNOWN);
+Verifier::PolicyMap Verifier::verifyHashes(const SuffixMap &packet_map,
+ const SuffixMap &suffix_map) {
+ PolicyMap policies;
- for (unsigned int i = 0; i < packets.size(); ++i) {
- uint32_t suffix = packets[i]->getName().getSuffix();
- auto manifest_hash = suffix_map.find(suffix);
+ for (const auto &packet_hash : packet_map) {
+ VerificationPolicy policy = VerificationPolicy::UNKNOWN;
+ auto manifest_hash = suffix_map.find(packet_hash.first);
if (manifest_hash != suffix_map.end()) {
- CryptoHashType hash_type = manifest_hash->second.first;
- CryptoHash packet_hash = packets[i]->computeDigest(hash_type);
-
- if (!CryptoHash::compareBinaryDigest(
- packet_hash.getDigest<uint8_t>().data(),
- manifest_hash->second.second.data(), hash_type)) {
- policies[i] = VerificationPolicy::ABORT;
- } else {
- policies[i] = VerificationPolicy::ACCEPT;
+ policy = VerificationPolicy::ABORT;
+
+ if (packet_hash.second == manifest_hash->second) {
+ policy = VerificationPolicy::ACCEPT;
}
}
- callVerificationFailedCallback(packets[i], policies[i]);
+ policies[packet_hash.first] = policy;
}
return policies;
}
-void Verifier::addKey(PARCKey *key) { parcVerifier_AddKey(verifier_, key); }
+Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets,
+ const SuffixMap &suffix_map) {
+ PolicyMap policies;
+
+ for (const auto &packet : packets) {
+ Suffix suffix = packet->getName().getSuffix();
+ VerificationPolicy policy = VerificationPolicy::UNKNOWN;
+ auto manifest_hash = suffix_map.find(suffix);
+
+ if (manifest_hash != suffix_map.end()) {
+ policy = VerificationPolicy::ABORT;
+ CryptoHashType hash_type = manifest_hash->second.getType();
+ CryptoHash packet_hash = packet->computeDigest(hash_type);
+
+ if (packet_hash == manifest_hash->second) {
+ policy = VerificationPolicy::ACCEPT;
+ }
+ }
-void Verifier::setHasher(PARCCryptoHasher *hasher) {
- parcAssertNotNull(hasher, "Expected non-null hasher");
- if (hasher_) parcCryptoHasher_Release(&hasher_);
- hasher_ = parcCryptoHasher_Acquire(hasher);
+ policies[suffix] = policy;
+ callVerificationFailedCallback(packet, policy);
+ }
+
+ return policies;
}
void Verifier::setVerificationFailedCallback(
@@ -192,27 +149,6 @@ void Verifier::getVerificationFailedCallback(
*verfication_failed_cb = &verification_failed_cb_;
}
-size_t Verifier::getSignatureSize(const PacketPtr packet) {
- return packet->getSignatureSize();
-}
-
-CryptoHash Verifier::computeHash(PacketPtr packet) {
- parcAssertNotNull(hasher_, "Expected non-null hasher");
-
- CryptoHasher crypto_hasher(hasher_);
- const utils::MemBuf &header_chain = *packet;
- const utils::MemBuf *current = &header_chain;
-
- crypto_hasher.init();
-
- do {
- crypto_hasher.updateBytes(current->data(), current->length());
- current = current->next();
- } while (current != &header_chain);
-
- return crypto_hasher.finalize();
-}
-
void Verifier::callVerificationFailedCallback(PacketPtr packet,
VerificationPolicy &policy) {
if (verification_failed_cb_ == interface::VOID_HANDLER) {
@@ -228,107 +164,222 @@ void Verifier::callVerificationFailedCallback(PacketPtr packet,
}
}
+// ---------------------------------------------------------
+// Void Verifier
+// ---------------------------------------------------------
bool VoidVerifier::verifyPacket(PacketPtr packet) { return true; }
-vector<VerificationPolicy> VoidVerifier::verifyPackets(
+bool VoidVerifier::verifyBuffer(const vector<uint8_t> &buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ return true;
+}
+
+bool VoidVerifier::verifyBuffer(const utils::MemBuf *buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ return true;
+}
+
+Verifier::PolicyMap VoidVerifier::verifyPackets(
const vector<PacketPtr> &packets) {
- return vector<VerificationPolicy>(packets.size(), VerificationPolicy::ACCEPT);
+ PolicyMap policies;
+
+ for (const auto &packet : packets) {
+ policies[packet->getName().getSuffix()] = VerificationPolicy::ACCEPT;
+ }
+
+ return policies;
}
-vector<VerificationPolicy> VoidVerifier::verifyPackets(
- const vector<PacketPtr> &packets,
- const unordered_map<Suffix, HashEntry> &suffix_map) {
- return vector<VerificationPolicy>(packets.size(), VerificationPolicy::ACCEPT);
+Verifier::PolicyMap VoidVerifier::verifyPackets(
+ const vector<PacketPtr> &packets, const SuffixMap &suffix_map) {
+ return verifyPackets(packets);
}
-AsymmetricVerifier::AsymmetricVerifier(PARCKey *pub_key) { addKey(pub_key); }
+// ---------------------------------------------------------
+// Asymmetric Verifier
+// ---------------------------------------------------------
+AsymmetricVerifier::AsymmetricVerifier(shared_ptr<EVP_PKEY> key) {
+ setKey(key);
+}
AsymmetricVerifier::AsymmetricVerifier(const string &cert_path) {
- setCertificate(cert_path);
+ useCertificate(cert_path);
+}
+
+AsymmetricVerifier::AsymmetricVerifier(shared_ptr<X509> cert) {
+ useCertificate(cert);
}
-void AsymmetricVerifier::setCertificate(const string &cert_path) {
- PARCCertificateFactory *factory = parcCertificateFactory_Create(
- PARCCertificateType_X509, PARCContainerEncoding_PEM);
+void AsymmetricVerifier::setKey(shared_ptr<EVP_PKEY> key) { key_ = key; };
- struct stat buffer;
- if (stat(cert_path.c_str(), &buffer) != 0) {
- throw errors::RuntimeException("Certificate does not exist");
+void AsymmetricVerifier::useCertificate(const string &cert_path) {
+ FILE *certf = fopen(cert_path.c_str(), "rb");
+
+ if (certf == nullptr) {
+ throw errors::RuntimeException("Certificate not found");
}
- PARCCertificate *certificate =
- parcCertificateFactory_CreateCertificateFromFile(factory,
- cert_path.c_str(), NULL);
- PARCKey *key = parcCertificate_GetPublicKey(certificate);
+ shared_ptr<X509> cert = shared_ptr<X509>(
+ PEM_read_X509(certf, nullptr, nullptr, nullptr), ::X509_free);
+ useCertificate(cert);
- addKey(key);
+ fclose(certf);
+}
- parcKey_Release(&key);
- parcCertificateFactory_Release(&factory);
+void AsymmetricVerifier::useCertificate(shared_ptr<X509> cert) {
+ key_ = shared_ptr<EVP_PKEY>(X509_get_pubkey(cert.get()), ::EVP_PKEY_free);
}
-SymmetricVerifier::SymmetricVerifier(const string &passphrase)
- : passphrase_(nullptr), signer_(nullptr) {
- setPassphrase(passphrase);
+bool AsymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
+
+ if (EVP_DigestVerifyInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ if (EVP_DigestVerifyUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
+
+ return EVP_DigestVerifyFinal(mdctx.get(), signature.data(),
+ signature.size()) == 1;
+}
+
+bool AsymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ const utils::MemBuf *p = buffer;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
+
+ if (EVP_DigestVerifyInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestVerifyUpdate(mdctx.get(), p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
+
+ p = p->next();
+ } while (p != buffer);
+
+ return EVP_DigestVerifyFinal(mdctx.get(), signature.data(),
+ signature.size()) == 1;
}
-SymmetricVerifier::~SymmetricVerifier() {
- if (passphrase_) parcBuffer_Release(&passphrase_);
- if (signer_) parcSigner_Release(&signer_);
+// ---------------------------------------------------------
+// Symmetric Verifier
+// ---------------------------------------------------------
+SymmetricVerifier::SymmetricVerifier(const string &passphrase) {
+ setPassphrase(passphrase);
}
+// Create and set a symmetric key from a passphrase.
void SymmetricVerifier::setPassphrase(const string &passphrase) {
- if (passphrase_) parcBuffer_Release(&passphrase_);
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_PutString(composer, passphrase.c_str());
- passphrase_ = parcBufferComposer_ProduceBuffer(composer);
- parcBufferComposer_Release(&composer);
+ key_ = shared_ptr<EVP_PKEY>(
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, nullptr,
+ (const unsigned char *)passphrase.c_str(),
+ passphrase.size()),
+ EVP_PKEY_free);
}
-void SymmetricVerifier::setSigner(const PARCCryptoSuite &suite) {
- parcAssertNotNull(passphrase_, "Expected non-null passphrase");
+bool SymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
- if (signer_) parcSigner_Release(&signer_);
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ vector<uint8_t> signature_bis(signature.size());
+ size_t signature_bis_len;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
- PARCSymmetricKeyStore *key_store = parcSymmetricKeyStore_Create(passphrase_);
- PARCSymmetricKeySigner *key_signer = parcSymmetricKeySigner_Create(
- key_store, parcCryptoSuite_GetCryptoHash(suite));
- signer_ = parcSigner_Create(key_signer, PARCSymmetricKeySignerAsSigner);
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
- PARCKeyId *key_id = parcSigner_CreateKeyId(signer_);
- PARCKey *key = parcKey_CreateFromSymmetricKey(
- key_id, parcSigner_GetSigningAlgorithm(signer_), passphrase_);
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
- addKey(key);
- setHasher(parcSigner_GetCryptoHasher(signer_));
+ if (EVP_DigestSignUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
- parcSymmetricKeyStore_Release(&key_store);
- parcSymmetricKeySigner_Release(&key_signer);
- parcKeyId_Release(&key_id);
- parcKey_Release(&key);
+ if (EVP_DigestSignFinal(mdctx.get(), signature_bis.data(),
+ &signature_bis_len) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
+
+ return signature == signature_bis && signature.size() == signature_bis_len;
}
-vector<VerificationPolicy> SymmetricVerifier::verifyPackets(
- const vector<PacketPtr> &packets) {
- vector<VerificationPolicy> policies(packets.size(), VerificationPolicy::DROP);
+bool SymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
- for (unsigned int i = 0; i < packets.size(); ++i) {
- auto suite =
- static_cast<PARCCryptoSuite>(packets[i]->getValidationAlgorithm());
+ const utils::MemBuf *p = buffer;
+ vector<uint8_t> signature_bis(signature.size());
+ size_t signature_bis_len;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
- if (!signer_ || suite != parcSigner_GetCryptoSuite(signer_)) {
- setSigner(suite);
- }
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
- if (verifyPacket(packets[i])) {
- policies[i] = VerificationPolicy::ACCEPT;
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestSignUpdate(mdctx.get(), p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
}
- callVerificationFailedCallback(packets[i], policies[i]);
+ p = p->next();
+ } while (p != buffer);
+
+ if (EVP_DigestSignFinal(mdctx.get(), signature_bis.data(),
+ &signature_bis_len) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
}
- return policies;
+ return signature == signature_bis && signature.size() == signature_bis_len;
}
} // namespace auth