From a5f7941f49160021506ecae0da090f0b204b75ea Mon Sep 17 00:00:00 2001 From: Olivier Roques Date: Thu, 17 Nov 2022 11:26:23 +0000 Subject: feat(auth): add support for ED25519 and ED448 Ref: HICN-818 Signed-off-by: Olivier Roques Change-Id: I8672f022b74be387e16496660a78edf3c1da4bf1 --- libtransport/src/auth/crypto_hash.cc | 73 +++++---------- libtransport/src/auth/crypto_suite.cc | 36 +++++-- libtransport/src/auth/signer.cc | 118 ++++++++--------------- libtransport/src/auth/verifier.cc | 172 +++++++++++++--------------------- 4 files changed, 154 insertions(+), 245 deletions(-) (limited to 'libtransport/src/auth') diff --git a/libtransport/src/auth/crypto_hash.cc b/libtransport/src/auth/crypto_hash.cc index bc2d5248e..0f6e9ab53 100644 --- a/libtransport/src/auth/crypto_hash.cc +++ b/libtransport/src/auth/crypto_hash.cc @@ -63,14 +63,16 @@ bool CryptoHash::operator==(const CryptoHash &other) const { } void CryptoHash::computeDigest(const uint8_t *buffer, size_t len) { - CryptoHashEVP hash_evp = CryptoHash::getEVP(digest_type_); - - if (hash_evp == nullptr) { + const EVP_MD *hash_md = CryptoHash::getMD(digest_type_); + if (hash_md == nullptr) { throw errors::RuntimeException("Unknown hash type"); } - EVP_Digest(buffer, len, digest_->writableData(), - (unsigned int *)&digest_size_, (*hash_evp)(), nullptr); + if (EVP_Digest(buffer, len, digest_->writableData(), + reinterpret_cast(&digest_size_), hash_md, + nullptr) != 1) { + throw errors::RuntimeException("Digest computation failed."); + }; } void CryptoHash::computeDigest(const std::vector &buffer) { @@ -78,33 +80,12 @@ void CryptoHash::computeDigest(const std::vector &buffer) { } 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_->writableData(), - (unsigned int *)&digest_size_) != 1) { - throw errors::RuntimeException("Digest computation failed"); + if (buffer->isChained()) { + throw errors::RuntimeException( + "Digest of chained membuf is not supported."); } - EVP_MD_CTX_free(mcdtx); + computeDigest(buffer->data(), buffer->length()); } const utils::MemBuf::Ptr &CryptoHash::getDigest() const { return digest_; } @@ -159,41 +140,33 @@ void CryptoHash::reset() { digest_->setLength(0); } -CryptoHashEVP CryptoHash::getEVP(CryptoHashType hash_type) { +const EVP_MD *CryptoHash::getMD(CryptoHashType hash_type) { switch (hash_type) { case CryptoHashType::SHA256: - return &EVP_sha256; + return EVP_sha256(); case CryptoHashType::SHA512: - return &EVP_sha512; + return EVP_sha512(); case CryptoHashType::BLAKE2S256: - return &EVP_blake2s256; + return EVP_blake2s256(); case CryptoHashType::BLAKE2B512: - return &EVP_blake2b512; + return EVP_blake2b512(); default: return nullptr; } } 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)()); + const EVP_MD *hash_md = CryptoHash::getMD(hash_type); + return hash_md == nullptr ? 0 : EVP_MD_size(hash_md); } 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( - memcmp(digest1, digest2, CryptoHash::getSize(hash_type))); + const EVP_MD *hash_md = CryptoHash::getMD(hash_type); + return hash_md == nullptr + ? false + : !static_cast( + memcmp(digest1, digest2, CryptoHash::getSize(hash_type))); } } // namespace auth diff --git a/libtransport/src/auth/crypto_suite.cc b/libtransport/src/auth/crypto_suite.cc index 44de85212..e7b097ac4 100644 --- a/libtransport/src/auth/crypto_suite.cc +++ b/libtransport/src/auth/crypto_suite.cc @@ -20,6 +20,10 @@ namespace auth { CryptoSuite getSuite(int nid) { switch (nid) { + case NID_ED25519: + return CryptoSuite::ED25519; + case NID_ED448: + return CryptoSuite::ED448; case NID_ecdsa_with_SHA256: return CryptoSuite::ECDSA_SHA256; case NID_ecdsa_with_SHA512: @@ -43,6 +47,10 @@ CryptoSuite getSuite(int nid) { std::string getStringSuite(CryptoSuite suite) { switch (suite) { + case CryptoSuite::ED25519: + return "ED25519"; + case CryptoSuite::ED448: + return "ED448"; case CryptoSuite::ECDSA_BLAKE2B512: return "ECDSA_BLAKE2B512"; case CryptoSuite::ECDSA_BLAKE2S256: @@ -82,30 +90,42 @@ std::string getStringSuite(CryptoSuite suite) { CryptoHashType getHashType(CryptoSuite suite) { switch (suite) { + case CryptoSuite::DSA_BLAKE2B512: case CryptoSuite::ECDSA_BLAKE2B512: - case CryptoSuite::RSA_BLAKE2B512: case CryptoSuite::HMAC_BLAKE2B512: - case CryptoSuite::DSA_BLAKE2B512: + case CryptoSuite::RSA_BLAKE2B512: return CryptoHashType::BLAKE2B512; + case CryptoSuite::DSA_BLAKE2S256: case CryptoSuite::ECDSA_BLAKE2S256: - case CryptoSuite::RSA_BLAKE2S256: case CryptoSuite::HMAC_BLAKE2S256: - case CryptoSuite::DSA_BLAKE2S256: + case CryptoSuite::RSA_BLAKE2S256: return CryptoHashType::BLAKE2S256; + case CryptoSuite::DSA_SHA256: case CryptoSuite::ECDSA_SHA256: - case CryptoSuite::RSA_SHA256: + case CryptoSuite::ED25519: + case CryptoSuite::ED448: case CryptoSuite::HMAC_SHA256: - case CryptoSuite::DSA_SHA256: + case CryptoSuite::RSA_SHA256: return CryptoHashType::SHA256; + case CryptoSuite::DSA_SHA512: case CryptoSuite::ECDSA_SHA512: - case CryptoSuite::RSA_SHA512: case CryptoSuite::HMAC_SHA512: - case CryptoSuite::DSA_SHA512: + case CryptoSuite::RSA_SHA512: return CryptoHashType::SHA512; default: return CryptoHashType::UNKNOWN; } } +const EVP_MD *getMD(CryptoSuite suite) { + switch (suite) { + case CryptoSuite::ED25519: + case CryptoSuite::ED448: + return nullptr; + default: + return CryptoHash::getMD(getHashType(suite)); + } +} + } // namespace auth } // namespace transport diff --git a/libtransport/src/auth/signer.cc b/libtransport/src/auth/signer.cc index 484180108..5fcb242be 100644 --- a/libtransport/src/auth/signer.cc +++ b/libtransport/src/auth/signer.cc @@ -86,87 +86,47 @@ void Signer::signPacket(PacketPtr packet) { } } -void Signer::signBuffer(const std::vector &buffer) { - DCHECK(key_ != nullptr); - CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType()); - - if (hash_evp == nullptr) { - throw errors::RuntimeException("Unknown hash type"); - } - - std::shared_ptr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free); +void Signer::signBuffer(const uint8_t *buffer, std::size_t len) { + const EVP_MD *hash_md = getMD(suite_); - if (mdctx == nullptr) { - throw errors::RuntimeException("Digest context allocation failed"); + std::shared_ptr 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_DigestSignUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) { - throw errors::RuntimeException("Digest update failed"); + if (EVP_DigestSignInit(md_ctx.get(), nullptr, hash_md, nullptr, key_.get()) != + 1) { + throw errors::RuntimeException("Signature initialization failed"); } - if (EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len_) != 1) { - throw errors::RuntimeException("Digest computation failed"); - } + if (EVP_DigestSign(md_ctx.get(), nullptr, &signature_len_, buffer, len) != + 1) { + throw errors::RuntimeException("Signature length computation failed"); + }; DCHECK(signature_len_ <= signature_->tailroom()); signature_->setLength(signature_len_); - if (EVP_DigestSignFinal(mdctx.get(), signature_->writableData(), - &signature_len_) != 1) { - throw errors::RuntimeException("Digest computation failed"); - } + if (EVP_DigestSign(md_ctx.get(), signature_->writableData(), &signature_len_, + buffer, len) != 1) { + throw errors::RuntimeException("Signature computation failed"); + }; DCHECK(signature_len_ <= signature_->tailroom()); signature_->setLength(signature_len_); } -void Signer::signBuffer(const utils::MemBuf *buffer) { - DCHECK(key_ != nullptr); - CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType()); - - if (hash_evp == nullptr) { - throw errors::RuntimeException("Unknown hash type"); - } - - const utils::MemBuf *p = buffer; - std::shared_ptr 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"); - } - - p = p->next(); - } while (p != buffer); - - if (EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len_) != 1) { - throw errors::RuntimeException("Digest computation failed"); - } - - DCHECK(signature_len_ <= signature_->tailroom()); - signature_->setLength(signature_len_); +void Signer::signBuffer(const std::vector &buffer) { + signBuffer(buffer.data(), buffer.size()); +} - if (EVP_DigestSignFinal(mdctx.get(), signature_->writableData(), - &signature_len_) != 1) { - throw errors::RuntimeException("Digest computation failed"); +void Signer::signBuffer(const utils::MemBuf *buffer) { + if (buffer->isChained()) { + throw errors::RuntimeException( + "Signature of chained membuf is not supported."); } - DCHECK(signature_len_ <= signature_->tailroom()); - signature_->setLength(signature_len_); + signBuffer(buffer->data(), buffer->length()); } const utils::MemBuf::Ptr &Signer::getSignature() const { return signature_; } @@ -208,6 +168,8 @@ void Signer::display() { // --------------------------------------------------------- void VoidSigner::signPacket(PacketPtr packet) {} +void VoidSigner::signBuffer(const uint8_t *buffer, std::size_t len) {} + void VoidSigner::signBuffer(const std::vector &buffer) {} void VoidSigner::signBuffer(const utils::MemBuf *buffer) {} @@ -258,20 +220,12 @@ void AsymmetricSigner::setKey(CryptoSuite suite, std::shared_ptr key, signature_len_ = EVP_PKEY_size(key_.get()); DCHECK(signature_len_ <= signature_->tailroom()); - signature_->setLength(signature_len_); - size_t enc_pbk_len = i2d_PublicKey(pub_key.get(), nullptr); - DCHECK(enc_pbk_len >= 0); - - uint8_t *enc_pbkey_raw = nullptr; - i2d_PublicKey(pub_key.get(), &enc_pbkey_raw); - DCHECK(enc_pbkey_raw != nullptr); - + // Key ID is not supported yet. + uint8_t id[8] = {0}; key_id_ = CryptoHash(getHashType()); - key_id_.computeDigest(enc_pbkey_raw, enc_pbk_len); - - OPENSSL_free(enc_pbkey_raw); + key_id_.computeDigest(id, 8); } size_t AsymmetricSigner::getSignatureFieldSize() const { @@ -296,18 +250,20 @@ SymmetricSigner::SymmetricSigner(CryptoSuite suite, (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) { + const EVP_MD *hash_md = getMD(suite_); + if (hash_md == nullptr) { throw errors::RuntimeException("Unknown hash type"); } - signature_len_ = EVP_MD_size((*hash_evp)()); + signature_len_ = EVP_MD_size(hash_md); DCHECK(signature_len_ <= signature_->tailroom()); signature_->setLength(signature_len_); - key_id_.computeDigest((uint8_t *)passphrase.c_str(), passphrase.size()); + + // Key ID is not supported yet. + uint8_t id[8] = {0}; + key_id_ = CryptoHash(getHashType()); + key_id_.computeDigest(id, 8); } } // namespace auth diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc index f930383e6..0919aec7d 100644 --- a/libtransport/src/auth/verifier.cc +++ b/libtransport/src/auth/verifier.cc @@ -42,9 +42,8 @@ bool Verifier::verifyPacket(PacketPtr packet) { throw errors::MalformedAHPacketException(); } - // Get crypto suite, hash type, signature length + // Get crypto suite CryptoSuite suite = packet->getValidationAlgorithm(); - CryptoHashType hash_type = getHashType(suite); // Copy IP+TCP / ICMP header before zeroing them u8 header_copy[HICN_HDRLEN_MAX]; @@ -69,8 +68,8 @@ bool Verifier::verifyPacket(PacketPtr packet) { packet->resetForHash(); // Check signatures - bool valid_packet = verifyBuffer(static_cast(packet), - signature_raw, hash_type); + bool valid_packet = + verifyBuffer(static_cast(packet), signature_raw, suite); // Restore header packet->loadHeader(header_copy, header_len); @@ -183,15 +182,21 @@ void Verifier::callVerificationFailedCallback(Suffix suffix, // --------------------------------------------------------- bool VoidVerifier::verifyPacket(PacketPtr packet) { return true; } +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 &buffer, const utils::MemBuf::Ptr &signature, - CryptoHashType hash_type) { + CryptoSuite suite) { return true; } bool VoidVerifier::verifyBuffer(const utils::MemBuf *buffer, const utils::MemBuf::Ptr &signature, - CryptoHashType hash_type) { + CryptoSuite suite) { return true; } @@ -250,65 +255,40 @@ void AsymmetricVerifier::useCertificate(std::shared_ptr cert) { std::shared_ptr(X509_get_pubkey(cert.get()), ::EVP_PKEY_free); } -bool AsymmetricVerifier::verifyBuffer(const std::vector &buffer, +bool AsymmetricVerifier::verifyBuffer(const uint8_t *buffer, std::size_t len, const utils::MemBuf::Ptr &signature, - CryptoHashType hash_type) { - CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type); + CryptoSuite suite) { + const EVP_MD *hash_md = getMD(suite); - if (hash_evp == nullptr) { - throw errors::RuntimeException("Unknown hash type"); + std::shared_ptr md_ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free); + if (md_ctx == nullptr) { + throw errors::RuntimeException("Signature context allocation failed"); } - std::shared_ptr 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, + 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->length()) == 1; +bool AsymmetricVerifier::verifyBuffer(const std::vector &buffer, + const utils::MemBuf::Ptr &signature, + CryptoSuite suite) { + return verifyBuffer(buffer.data(), buffer.size(), signature, suite); } bool AsymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer, const utils::MemBuf::Ptr &signature, - CryptoHashType hash_type) { - CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type); - - if (hash_evp == nullptr) { - throw errors::RuntimeException("Unknown hash type"); + CryptoSuite suite) { + if (buffer->isChained()) { + throw errors::RuntimeException( + "Signature of chained membuf is not supported."); } - const utils::MemBuf *p = buffer; - std::shared_ptr 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->length()) == 1; + return verifyBuffer(buffer->data(), buffer->length(), signature, suite); } // --------------------------------------------------------- @@ -327,83 +307,63 @@ void SymmetricVerifier::setPassphrase(const std::string &passphrase) { EVP_PKEY_free); } -bool SymmetricVerifier::verifyBuffer(const std::vector &buffer, +bool SymmetricVerifier::verifyBuffer(const uint8_t *buffer, std::size_t len, const utils::MemBuf::Ptr &signature, - CryptoHashType hash_type) { - CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type); - - if (hash_evp == nullptr) { + CryptoSuite suite) { + const EVP_MD *hash_md = getMD(suite); + if (hash_md == nullptr) { throw errors::RuntimeException("Unknown hash type"); } const utils::MemBuf::Ptr &signature_bis = core::PacketManager<>::getInstance().getMemBuf(); - signature_bis->append(signature->length()); size_t signature_bis_len; - std::shared_ptr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free); - if (mdctx == nullptr) { - throw errors::RuntimeException("Digest context allocation failed"); + std::shared_ptr 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->writableData(), - &signature_bis_len) != 1) { - throw errors::RuntimeException("Digest computation failed"); - } + DCHECK(signature_bis_len <= signature_bis->tailroom()); + signature_bis->append(signature_bis_len); + + if (EVP_DigestSign(md_ctx.get(), signature_bis->writableData(), + &signature_bis_len, buffer, len) != 1) { + throw errors::RuntimeException("Signature computation failed"); + }; + + DCHECK(signature_bis_len <= signature_bis->tailroom()); + signature_bis->setLength(signature_bis_len); return signature->length() == signature_bis_len && *signature == *signature_bis; } -bool SymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer, +bool SymmetricVerifier::verifyBuffer(const std::vector &buffer, const utils::MemBuf::Ptr &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; - const utils::MemBuf::Ptr &signature_bis = - core::PacketManager<>::getInstance().getMemBuf(); - signature_bis->append(signature->length()); - size_t signature_bis_len; - std::shared_ptr 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"); - } - - p = p->next(); - } while (p != buffer); + CryptoSuite suite) { + return verifyBuffer(buffer.data(), buffer.size(), signature, suite); +} - if (EVP_DigestSignFinal(mdctx.get(), signature_bis->writableData(), - &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->length() == signature_bis_len && - *signature == *signature_bis; + return verifyBuffer(buffer->data(), buffer->length(), signature, suite); } } // namespace auth -- cgit 1.2.3-korg