From f41c8fef99497e357965ef3514bb7b5282a2e938 Mon Sep 17 00:00:00 2001 From: Adrien Beraud <adrien.beraud@savoirfairelinux.com> Date: Thu, 20 Apr 2017 16:48:55 +0200 Subject: [PATCH] crypto: unify API across GnuTLS versions Throw an exception if GnuTLS is too old instead of not providing the API. Also consistently throw in case of hash error, and return 0 for an empty hash, for both PublicKey and Certificate. --- include/opendht/crypto.h | 4 ---- include/opendht/securedht.h | 3 +-- src/crypto.cpp | 40 ++++++++++++++++++++++++++----------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h index ef87b415..8a1f86bd 100644 --- a/include/opendht/crypto.h +++ b/include/opendht/crypto.h @@ -83,9 +83,7 @@ struct OPENDHT_PUBLIC PublicKey PublicKey& operator=(PublicKey&& o) noexcept; InfoHash getId() const; -#if GNUTLS_VERSION_NUMBER >= 0x030401 PkId getLongId() const; -#endif bool checkSignature(const Blob& data, const Blob& signature) const; Blob encrypt(const Blob&) const; @@ -364,9 +362,7 @@ struct OPENDHT_PUBLIC Certificate { /** Same as getPublicKey().getId() */ InfoHash getId() const; -#if GNUTLS_VERSION_NUMBER >= 0x030401 PkId getLongId() const; -#endif /** Read certificate Common Name (CN) */ std::string getName() const; diff --git a/include/opendht/securedht.h b/include/opendht/securedht.h index 7e2004d9..acae729f 100644 --- a/include/opendht/securedht.h +++ b/include/opendht/securedht.h @@ -51,11 +51,10 @@ public: InfoHash getId() const { return key_ ? key_->getPublicKey().getId() : InfoHash(); } -#if GNUTLS_VERSION_NUMBER >= 0x030401 PkId getLongId() const { return key_ ? key_->getPublicKey().getLongId() : PkId(); } -#endif + ValueType secureType(ValueType&& type); ValueType secureType(const ValueType& type) { diff --git a/src/crypto.cpp b/src/crypto.cpp index 4b35b1ec..ec3ce321 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -525,24 +525,34 @@ PublicKey::encrypt(const Blob& data) const InfoHash PublicKey::getId() const { + if (not pk) + return {}; InfoHash id; size_t sz = id.size(); - if (gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz) != GNUTLS_E_SUCCESS || sz != id.size()) - return {}; + if (auto err = gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz)) + throw CryptoException(std::string("Can't get public key ID: ") + gnutls_strerror(err)); + if (sz != id.size()) + throw CryptoException("Can't get public key ID: wrong output length."); return id; } -#if GNUTLS_VERSION_NUMBER >= 0x030401 PkId PublicKey::getLongId() const { + if (not pk) + return {}; +#if GNUTLS_VERSION_NUMBER < 0x030401 + throw CryptoException("Can't get 256 bits public key ID: GnuTLS 3.4.1 or higher required."); +#else PkId h; size_t sz = h.size(); - if (gnutls_pubkey_get_key_id(pk, GNUTLS_KEYID_USE_SHA256, h.data(), &sz) != GNUTLS_E_SUCCESS || sz != h.size()) - return {}; + if (auto err = gnutls_pubkey_get_key_id(pk, GNUTLS_KEYID_USE_SHA256, h.data(), &sz)) + throw CryptoException(std::string("Can't get 256 bits public key ID: ") + gnutls_strerror(err)); + if (sz != h.size()) + throw CryptoException("Can't get 256 bits public key ID: wrong output length."); return h; -} #endif +} Certificate::Certificate(const Blob& certData) : cert(nullptr) { @@ -643,24 +653,30 @@ Certificate::getId() const return {}; InfoHash id; size_t sz = id.size(); - if (gnutls_x509_crt_get_key_id(cert, 0, id.data(), &sz) != GNUTLS_E_SUCCESS || sz != id.size()) - throw CryptoException("Can't get certificate public key ID."); + if (auto err = gnutls_x509_crt_get_key_id(cert, 0, id.data(), &sz)) + throw CryptoException(std::string("Can't get certificate public key ID: ") + gnutls_strerror(err)); + if (sz != id.size()) + throw CryptoException("Can't get certificate public key ID: wrong output length."); return id; } -#if GNUTLS_VERSION_NUMBER >= 0x030401 PkId Certificate::getLongId() const { if (not cert) return {}; +#if GNUTLS_VERSION_NUMBER < 0x030401 + throw CryptoException("Can't get certificate 256 bits public key ID: GnuTLS 3.4.1 or higher required."); +#else PkId id; size_t sz = id.size(); - if (gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, id.data(), &sz) != GNUTLS_E_SUCCESS || sz != id.size()) - throw CryptoException("Can't get certificate public key ID."); + if (auto err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, id.data(), &sz)) + throw CryptoException(std::string("Can't get certificate 256 bits public key ID: ") + gnutls_strerror(err)); + if (sz != id.size()) + throw CryptoException("Can't get certificate 256 bits public key ID: wrong output length."); return id; -} #endif +} static std::string getDN(gnutls_x509_crt_t cert, const char* oid, bool issuer = false) -- GitLab