diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h index 4f66b7646fb389ec4d45393b08ca2c7f7e473e8e..7d9c8f2f4de54a8cda761060d0d3417846ad3096 100644 --- a/include/opendht/crypto.h +++ b/include/opendht/crypto.h @@ -373,7 +373,8 @@ struct OPENDHT_PUBLIC Certificate { std::chrono::system_clock::time_point getExpiration() const; /** - * Returns true if the certificate is marked as a Certificate Authority. + * Returns true if the certificate is marked as a Certificate Authority + * and has necessary key usage flags to sign certificates. */ bool isCA() const; diff --git a/src/crypto.cpp b/src/crypto.cpp index d7a30c6395b8cfe5832d223703d411b45023d673..80c1dc802b9a9659f162c64769deaa2059753087 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -722,7 +722,20 @@ bool Certificate::isCA() const { unsigned critical; - return gnutls_x509_crt_get_ca_status(cert, &critical) > 0; + bool ca_flag = gnutls_x509_crt_get_ca_status(cert, &critical) > 0; + if (ca_flag) { + unsigned usage; + auto ret = gnutls_x509_crt_get_key_usage(cert, &usage, &critical); + /* Conforming CAs MUST include this extension in certificates that + contain public keys that are used to validate digital signatures on + other public key certificates or CRLs. */ + if (ret < 0) + return false; + if (not critical) + return true; + return usage & GNUTLS_KEY_KEY_CERT_SIGN; + } + return false; } std::string