From cab2744536dcabeca38f770ec8268fcf5d9279fb Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Sun, 11 Jun 2023 13:54:03 +0100 Subject: Implement support for SPKI fingerprints into the ssl_gnutls module. --- src/modules/extra/m_ssl_gnutls.cpp | 47 +++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index bd7b249b3..5ee85d3e1 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -45,6 +45,7 @@ #include "timeutils.h" #include +#include #include #include @@ -480,6 +481,9 @@ namespace GnuTLS */ const bool requestclientcert; + /** Whether the fingerprint is a SPKI fingerprint or not. */ + bool spkifp; + static std::string ReadFile(const std::string& filename) { FileReader reader(filename); @@ -534,6 +538,7 @@ namespace GnuTLS unsigned int outrecsize; bool requestclientcert; + bool spkifp; Config(const std::string& profilename, const std::shared_ptr& tag) : name(profilename) @@ -546,6 +551,7 @@ namespace GnuTLS , mindh(tag->getNum("mindhbits", 1024)) , hashstr(tag->getString("hash", "sha256", 1)) , requestclientcert(tag->getBool("requestclientcert", true)) + , spkifp(tag->getBool("spkifp")) { // Load trusted CA and revocation list, if set std::string filename = tag->getString("cafile"); @@ -570,6 +576,7 @@ namespace GnuTLS , priority(config.priostr) , outrecsize(config.outrecsize) , requestclientcert(config.requestclientcert) + , spkifp(config.spkifp) { #ifndef GNUTLS_AUTO_DH x509cred.SetDH(config.dh); @@ -593,6 +600,7 @@ namespace GnuTLS X509Credentials& GetX509Credentials() { return x509cred; } gnutls_digest_algorithm_t GetHash() const { return hash.get(); } unsigned int GetOutgoingRecordSize() const { return outrecsize; } + bool UseSPKI() const { return spkifp; } }; } @@ -661,6 +669,42 @@ private: } } + int GetCertFP(gnutls_x509_crt_t& cert, char* buffer, size_t& buffer_size) + { + return gnutls_x509_crt_get_fingerprint(cert, GetProfile().GetHash(), buffer, &buffer_size); + } + + int GetSPKIFP(gnutls_x509_crt_t& cert, char* buffer, size_t& buffer_size) + { + int ret; + gnutls_pubkey_t pubkey; + + if ((ret = gnutls_pubkey_init(&pubkey)) != GNUTLS_E_SUCCESS) + return ret; + + if ((ret = gnutls_pubkey_import_x509(pubkey, cert, 0)) != GNUTLS_E_SUCCESS) + { + gnutls_pubkey_deinit(pubkey); + return ret; + } + + // We need to do this twice in order to find the size of the public key. + size_t derkey_size = 0; + if (gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, buffer, &derkey_size) != GNUTLS_E_SHORT_MEMORY_BUFFER) + return GNUTLS_E_SHORT_MEMORY_BUFFER; + + std::vector derkey(derkey_size); + if ((ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, &derkey[0], &derkey_size)) != GNUTLS_E_SUCCESS) + return ret; + + gnutls_pubkey_deinit(pubkey); + if (gnutls_hash_fast(GetProfile().GetHash(), &derkey[0], derkey_size, buffer) != GNUTLS_E_SUCCESS) + return ret; + + buffer_size = gnutls_hash_get_len(GetProfile().GetHash()); + return GNUTLS_E_SUCCESS; + } + void VerifyCertificate() { auto* certinfo = new ssl_cert(); @@ -719,7 +763,8 @@ private: ProcessDNString(buffer, buffer_size, certinfo->issuer); buffer_size = sizeof(buffer); - if ((ret = gnutls_x509_crt_get_fingerprint(cert, GetProfile().GetHash(), buffer, &buffer_size)) < 0) + ret = GetProfile().UseSPKI() ? GetSPKIFP(cert, buffer, buffer_size) : GetCertFP(cert, buffer, buffer_size); + if (ret != GNUTLS_E_SUCCESS) { certinfo->error = gnutls_strerror(ret); } -- cgit v1.3.1-10-gc9f91