diff options
Diffstat (limited to 'libtransport/src/auth/verifier.cc')
-rw-r--r-- | libtransport/src/auth/verifier.cc | 284 |
1 files changed, 134 insertions, 150 deletions
diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc index c9ac1650f..0919aec7d 100644 --- a/libtransport/src/auth/verifier.cc +++ b/libtransport/src/auth/verifier.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 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: @@ -14,14 +14,16 @@ */ #include <hicn/transport/auth/verifier.h> +#include <hicn/transport/core/global_object_pool.h> +#include <hicn/transport/core/interest.h> #include <protocols/errors.h> -using namespace std; +#include "glog/logging.h" namespace transport { namespace auth { -const vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = { +const std::vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = { VerificationPolicy::DROP, VerificationPolicy::ABORT, }; @@ -36,42 +38,55 @@ Verifier::Verifier() Verifier::~Verifier() {} bool Verifier::verifyPacket(PacketPtr packet) { - core::Packet::Format format = packet->getFormat(); - - if (!packet->authenticationHeader()) { + if (!packet->hasAH()) { throw errors::MalformedAHPacketException(); } - // Get crypto suite, hash type, signature length + // Get crypto suite 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); + u8 header_copy[HICN_HDRLEN_MAX]; + size_t header_len; + packet->saveHeader(header_copy, &header_len); + + // Copy bitmap from interest manifest + uint32_t request_bitmap[BITMAP_SIZE] = {0}; + if (packet->isInterest()) { + core::Interest *interest = dynamic_cast<core::Interest *>(packet); + memcpy(request_bitmap, interest->getRequestBitmap(), + BITMAP_SIZE * sizeof(uint32_t)); + } // Retrieve packet signature - uint8_t *packet_signature = packet->getSignature(); - vector<uint8_t> signature_raw(packet_signature, - packet_signature + signature_len); + utils::MemBuf::Ptr signature_raw = packet->getSignature(); + std::size_t signature_len = packet->getSignatureSize(); + DCHECK(signature_len <= signature_raw->tailroom()); + signature_raw->setLength(signature_len); // Reset fields that are not used to compute signature packet->resetForHash(); // Check signatures - bool valid_packet = verifyBuffer(static_cast<utils::MemBuf *>(packet), - signature_raw, hash_type); + bool valid_packet = + verifyBuffer(static_cast<utils::MemBuf *>(packet), signature_raw, suite); // Restore header - hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false); - packet->setSignatureSizeGap(packet->getSignatureSize() - signature_len); + packet->loadHeader(header_copy, header_len); + packet->setSignature(signature_raw); + packet->setSignatureSize(signature_raw->length()); + + // Restore bitmap in interest manifest + if (packet->isInterest()) { + core::Interest *interest = dynamic_cast<core::Interest *>(packet); + interest->setRequestBitmap(request_bitmap); + } return valid_packet; } -Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets) { +Verifier::PolicyMap Verifier::verifyPackets( + const std::vector<PacketPtr> &packets) { PolicyMap policies; for (const auto &packet : packets) { @@ -82,8 +97,8 @@ Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets) { policy = VerificationPolicy::ACCEPT; } + callVerificationFailedCallback(suffix, policy); policies[suffix] = policy; - callVerificationFailedCallback(packet, policy); } return policies; @@ -105,14 +120,15 @@ Verifier::PolicyMap Verifier::verifyHashes(const SuffixMap &packet_map, } } + callVerificationFailedCallback(packet_hash.first, policy); policies[packet_hash.first] = policy; } return policies; } -Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets, - const SuffixMap &suffix_map) { +Verifier::PolicyMap Verifier::verifyPackets( + const std::vector<PacketPtr> &packets, const SuffixMap &suffix_map) { PolicyMap policies; for (const auto &packet : packets) { @@ -130,8 +146,8 @@ Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets, } } + callVerificationFailedCallback(suffix, policy); policies[suffix] = policy; - callVerificationFailedCallback(packet, policy); } return policies; @@ -139,7 +155,7 @@ Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets, void Verifier::setVerificationFailedCallback( VerificationFailedCallback verfication_failed_cb, - const vector<VerificationPolicy> &failed_policies) { + const std::vector<VerificationPolicy> &failed_policies) { verification_failed_cb_ = verfication_failed_cb; failed_policies_ = failed_policies; } @@ -149,7 +165,7 @@ void Verifier::getVerificationFailedCallback( *verfication_failed_cb = &verification_failed_cb_; } -void Verifier::callVerificationFailedCallback(PacketPtr packet, +void Verifier::callVerificationFailedCallback(Suffix suffix, VerificationPolicy &policy) { if (verification_failed_cb_ == interface::VOID_HANDLER) { return; @@ -157,10 +173,7 @@ void Verifier::callVerificationFailedCallback(PacketPtr packet, if (find(failed_policies_.begin(), failed_policies_.end(), policy) != failed_policies_.end()) { - policy = verification_failed_cb_( - static_cast<const core::ContentObject &>(*packet), - make_error_code( - protocol::protocol_error::signature_verification_failed)); + policy = verification_failed_cb_(suffix, policy); } } @@ -169,217 +182,188 @@ void Verifier::callVerificationFailedCallback(PacketPtr packet, // --------------------------------------------------------- bool VoidVerifier::verifyPacket(PacketPtr packet) { return true; } -bool VoidVerifier::verifyBuffer(const vector<uint8_t> &buffer, - const vector<uint8_t> &signature, - CryptoHashType hash_type) { +bool VoidVerifier::verifyBuffer(const uint8_t *buffer, std::size_t len, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + return true; +} + +bool VoidVerifier::verifyBuffer(const std::vector<uint8_t> &buffer, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { return true; } bool VoidVerifier::verifyBuffer(const utils::MemBuf *buffer, - const vector<uint8_t> &signature, - CryptoHashType hash_type) { + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { return true; } Verifier::PolicyMap VoidVerifier::verifyPackets( - const vector<PacketPtr> &packets) { + const std::vector<PacketPtr> &packets) { PolicyMap policies; for (const auto &packet : packets) { - policies[packet->getName().getSuffix()] = VerificationPolicy::ACCEPT; + auth::Suffix suffix = packet->getName().getSuffix(); + VerificationPolicy policy = VerificationPolicy::ACCEPT; + callVerificationFailedCallback(suffix, policy); + policies[suffix] = policy; } return policies; } Verifier::PolicyMap VoidVerifier::verifyPackets( - const vector<PacketPtr> &packets, const SuffixMap &suffix_map) { + const std::vector<PacketPtr> &packets, const SuffixMap &suffix_map) { return verifyPackets(packets); } // --------------------------------------------------------- // Asymmetric Verifier // --------------------------------------------------------- -AsymmetricVerifier::AsymmetricVerifier(shared_ptr<EVP_PKEY> key) { +AsymmetricVerifier::AsymmetricVerifier(std::shared_ptr<EVP_PKEY> key) { setKey(key); } -AsymmetricVerifier::AsymmetricVerifier(const string &cert_path) { +AsymmetricVerifier::AsymmetricVerifier(const std::string &cert_path) { useCertificate(cert_path); } -AsymmetricVerifier::AsymmetricVerifier(shared_ptr<X509> cert) { +AsymmetricVerifier::AsymmetricVerifier(std::shared_ptr<X509> cert) { useCertificate(cert); } -void AsymmetricVerifier::setKey(shared_ptr<EVP_PKEY> key) { key_ = key; }; +void AsymmetricVerifier::setKey(std::shared_ptr<EVP_PKEY> key) { key_ = key; }; -void AsymmetricVerifier::useCertificate(const string &cert_path) { +void AsymmetricVerifier::useCertificate(const std::string &cert_path) { FILE *certf = fopen(cert_path.c_str(), "rb"); if (certf == nullptr) { throw errors::RuntimeException("Certificate not found"); } - shared_ptr<X509> cert = shared_ptr<X509>( + std::shared_ptr<X509> cert = std::shared_ptr<X509>( PEM_read_X509(certf, nullptr, nullptr, nullptr), ::X509_free); useCertificate(cert); fclose(certf); } -void AsymmetricVerifier::useCertificate(shared_ptr<X509> cert) { - key_ = shared_ptr<EVP_PKEY>(X509_get_pubkey(cert.get()), ::EVP_PKEY_free); +void AsymmetricVerifier::useCertificate(std::shared_ptr<X509> cert) { + key_ = + std::shared_ptr<EVP_PKEY>(X509_get_pubkey(cert.get()), ::EVP_PKEY_free); } -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); +bool AsymmetricVerifier::verifyBuffer(const uint8_t *buffer, std::size_t len, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + const EVP_MD *hash_md = getMD(suite); - if (mdctx == nullptr) { - throw errors::RuntimeException("Digest context allocation failed"); + std::shared_ptr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free); + if (md_ctx == nullptr) { + throw errors::RuntimeException("Signature context allocation failed"); } - if (EVP_DigestVerifyInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr, + if (EVP_DigestVerifyInit(md_ctx.get(), nullptr, hash_md, nullptr, key_.get()) != 1) { - throw errors::RuntimeException("Digest initialization failed"); + throw errors::RuntimeException("Signature initialization failed"); } - if (EVP_DigestVerifyUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) { - throw errors::RuntimeException("Digest update failed"); - } + return EVP_DigestVerify(md_ctx.get(), signature->data(), signature->length(), + buffer, len) == 1; +}; - return EVP_DigestVerifyFinal(mdctx.get(), signature.data(), - signature.size()) == 1; +bool AsymmetricVerifier::verifyBuffer(const std::vector<uint8_t> &buffer, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + return verifyBuffer(buffer.data(), buffer.size(), signature, suite); } 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"); + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + if (buffer->isChained()) { + throw errors::RuntimeException( + "Signature of chained membuf is not supported."); } - 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; + return verifyBuffer(buffer->data(), buffer->length(), signature, suite); } // --------------------------------------------------------- // Symmetric Verifier // --------------------------------------------------------- -SymmetricVerifier::SymmetricVerifier(const string &passphrase) { +SymmetricVerifier::SymmetricVerifier(const std::string &passphrase) { setPassphrase(passphrase); } // Create and set a symmetric key from a passphrase. -void SymmetricVerifier::setPassphrase(const string &passphrase) { - key_ = shared_ptr<EVP_PKEY>( +void SymmetricVerifier::setPassphrase(const std::string &passphrase) { + key_ = std::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); } -bool SymmetricVerifier::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) { +bool SymmetricVerifier::verifyBuffer(const uint8_t *buffer, std::size_t len, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + const EVP_MD *hash_md = getMD(suite); + if (hash_md == nullptr) { throw errors::RuntimeException("Unknown hash type"); } - vector<uint8_t> signature_bis(signature.size()); + const utils::MemBuf::Ptr &signature_bis = + core::PacketManager<>::getInstance().getMemBuf(); size_t signature_bis_len; - shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free); - if (mdctx == nullptr) { - throw errors::RuntimeException("Digest context allocation failed"); + std::shared_ptr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free); + if (md_ctx == nullptr) { + throw errors::RuntimeException("Signature context allocation failed"); } - if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr, - key_.get()) != 1) { - throw errors::RuntimeException("Digest initialization failed"); + if (EVP_DigestSignInit(md_ctx.get(), nullptr, hash_md, nullptr, key_.get()) != + 1) { + throw errors::RuntimeException("Signature initialization failed"); } - if (EVP_DigestSignUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) { - throw errors::RuntimeException("Digest update failed"); - } + if (EVP_DigestSign(md_ctx.get(), nullptr, &signature_bis_len, buffer, len) != + 1) { + throw errors::RuntimeException("Signature length computation failed"); + }; - if (EVP_DigestSignFinal(mdctx.get(), signature_bis.data(), - &signature_bis_len) != 1) { - throw errors::RuntimeException("Digest computation failed"); - } + DCHECK(signature_bis_len <= signature_bis->tailroom()); + signature_bis->append(signature_bis_len); - return signature == signature_bis && signature.size() == signature_bis_len; -} - -bool SymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer, - const vector<uint8_t> &signature, - CryptoHashType hash_type) { - CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type); + if (EVP_DigestSign(md_ctx.get(), signature_bis->writableData(), + &signature_bis_len, buffer, len) != 1) { + throw errors::RuntimeException("Signature computation failed"); + }; - if (hash_evp == nullptr) { - throw errors::RuntimeException("Unknown hash type"); - } + DCHECK(signature_bis_len <= signature_bis->tailroom()); + signature_bis->setLength(signature_bis_len); - 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 (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"); - } + return signature->length() == signature_bis_len && + *signature == *signature_bis; +} - p = p->next(); - } while (p != buffer); +bool SymmetricVerifier::verifyBuffer(const std::vector<uint8_t> &buffer, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + return verifyBuffer(buffer.data(), buffer.size(), signature, suite); +} - if (EVP_DigestSignFinal(mdctx.get(), signature_bis.data(), - &signature_bis_len) != 1) { - throw errors::RuntimeException("Digest computation failed"); +bool SymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + if (buffer->isChained()) { + throw errors::RuntimeException( + "Signature of chained membuf is not supported."); } - return signature == signature_bis && signature.size() == signature_bis_len; + return verifyBuffer(buffer->data(), buffer->length(), signature, suite); } } // namespace auth |