Deprecate MD5 fingerprints for SHA256
authorFrank Zschockelt <lm@freakysoft.de>
Sat, 13 Feb 2016 12:16:45 +0100
changeset 704 d682ae8d7d3a
parent 703 f9b3bb67ce34
child 705 1b455131d0f1
Deprecate MD5 fingerprints for SHA256
loudmouth/lm-ssl-base.c
loudmouth/lm-ssl-base.h
loudmouth/lm-ssl-generic.c
loudmouth/lm-ssl-gnutls.c
loudmouth/lm-ssl-openssl.c
loudmouth/lm-ssl.h
--- a/loudmouth/lm-ssl-base.c	Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-base.c	Sat Feb 13 12:16:45 2016 +0100
@@ -16,6 +16,7 @@
  * License along with this program; if not, see <https://www.gnu.org/licenses>
  */
 
+#include "lm-debug.h"
 #include "lm-ssl-base.h"
 #include "lm-ssl-internals.h"
 
@@ -34,7 +35,15 @@
     base->cipher_list    = NULL;
 
     if (expected_fingerprint) {
-        base->expected_fingerprint = g_memdup (expected_fingerprint, 16);
+        if (!g_str_has_prefix(expected_fingerprint, LM_FINGERPRINT_PREFIX)) {
+          /* let's set a bogus hash because the user tries to use a hash
+             we don't support now */
+          expected_fingerprint = "wrong_hash_format";
+          g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "Wrong hash format, use "
+                 LM_FINGERPRINT_PREFIX"$hash");
+        }
+        base->expected_fingerprint = g_strndup(expected_fingerprint,
+                                               LM_FINGERPRINT_LENGTH);
     } else {
         base->expected_fingerprint = NULL;
     }
@@ -64,6 +73,39 @@
         g_free (base->ca_path);
     base->ca_path = g_strdup (ca_path);
 }
+
+void
+_lm_ssl_base_set_fingerprint (LmSSLBase    *base,
+                              const guchar *digest,
+                              unsigned int  digest_len)
+{
+    gchar hex[LM_FINGERPRINT_LENGTH];
+    gchar *p;
+    int i;
+
+    g_assert(LM_FINGERPRINT_PREFIX != NULL);
+    g_assert(digest != NULL);
+    g_assert(digest_len > 0);
+    g_assert(LM_FINGERPRINT_LENGTH >=
+             (sizeof(LM_FINGERPRINT_PREFIX) + digest_len*2));
+
+    for (p = hex, i = 0; i < digest_len ; i++, p+=2) {
+        g_snprintf(p, 3, "%02x", digest[i]);
+    }
+    g_snprintf(base->fingerprint, LM_FINGERPRINT_LENGTH,
+               "%s%s",
+               LM_FINGERPRINT_PREFIX,
+               hex);
+}
+
+int _lm_ssl_base_check_fingerprint( LmSSLBase *base)
+{
+    if (base->expected_fingerprint == NULL) {
+        return 0;
+    }
+    return g_ascii_strcasecmp(base->expected_fingerprint, base->fingerprint);
+}
+
 void
 _lm_ssl_base_free_fields (LmSSLBase *base)
 {
--- a/loudmouth/lm-ssl-base.h	Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-base.h	Sat Feb 13 12:16:45 2016 +0100
@@ -31,7 +31,7 @@
     gchar          *cipher_list;
     gchar          *ca_path;
     gchar          *expected_fingerprint;
-    char            fingerprint[20];
+    char            fingerprint[LM_FINGERPRINT_LENGTH];
     gboolean        use_starttls;
     gboolean        require_starttls;
 
@@ -50,6 +50,12 @@
 void _lm_ssl_base_set_ca_path (LmSSLBase   *base,
                                const gchar *ca_path);
 
+void _lm_ssl_base_set_fingerprint (LmSSLBase    *base,
+                                   const guchar *digest,
+                                   unsigned int  digest_len);
+
+int _lm_ssl_base_check_fingerprint( LmSSLBase *base);
+
 void _lm_ssl_base_free_fields  (LmSSLBase      *base);
 
 #endif /* __LM_SSL_BASE_H__ */
--- a/loudmouth/lm-ssl-generic.c	Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-generic.c	Sat Feb 13 12:16:45 2016 +0100
@@ -136,9 +136,9 @@
  * lm_ssl_get_fingerprint:
  * @ssl: an #LmSSL
  *
- * Returns the MD5 fingerprint of the remote server's certificate.
+ * Returns the fingerprint of the remote server's certificate.
  *
- * Return value: A 16-byte array representing the fingerprint or %NULL if unknown.
+ * Return value: A null terminated string representing the fingerprint or %NULL if unknown.
  **/
 const gchar *
 lm_ssl_get_fingerprint (LmSSL *ssl)
--- a/loudmouth/lm-ssl-gnutls.c	Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-gnutls.c	Sat Feb 13 12:16:45 2016 +0100
@@ -34,6 +34,7 @@
 #ifdef HAVE_GNUTLS
 
 #include <gnutls/x509.h>
+#include <gnutls/crypto.h>
 
 struct _LmSSL {
     LmSSLBase base;
@@ -109,6 +110,8 @@
     if (gnutls_certificate_type_get (ssl->gnutls_session) == GNUTLS_CRT_X509) {
         const gnutls_datum_t* cert_list;
         guint cert_list_size;
+        gnutls_digest_algorithm_t digest = GNUTLS_DIG_SHA256;
+        guchar digest_bin[LM_FINGERPRINT_LENGTH];
         size_t digest_size;
         gnutls_x509_crt_t cert;
 
@@ -139,15 +142,15 @@
 
         gnutls_x509_crt_deinit (cert);
 
-        digest_size = sizeof (base->fingerprint);
+        digest_size = gnutls_hash_get_len(digest);
+        g_assert(digest_size < sizeof(digest_bin));
 
-        if (gnutls_fingerprint (GNUTLS_DIG_MD5, &cert_list[0],
-                                base->fingerprint,
+        if (gnutls_fingerprint (digest,
+                                &cert_list[0],
+                                digest_bin,
                                 &digest_size) >= 0) {
-            if (base->expected_fingerprint &&
-                memcmp (base->expected_fingerprint,
-                        base->fingerprint,
-                        digest_size) &&
+            _lm_ssl_base_set_fingerprint(base, digest_bin, digest_size);
+            if (_lm_ssl_base_check_fingerprint(base) != 0 &&
                 base->func (ssl,
                             LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
                             base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
--- a/loudmouth/lm-ssl-openssl.c	Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-openssl.c	Sat Feb 13 12:16:45 2016 +0100
@@ -126,8 +126,9 @@
     LmSSLBase *base;
     long verify_res;
     int rc;
-    const EVP_MD *digest = EVP_md5();
+    const EVP_MD *digest = EVP_sha256();
     unsigned int digest_len;
+    guchar digest_bin[EVP_MD_size(digest)];
     X509 *srv_crt;
     gchar *cn;
     X509_NAME *crt_subj;
@@ -143,17 +144,14 @@
 
     verify_res = SSL_get_verify_result(ssl->ssl);
     srv_crt = SSL_get_peer_certificate(ssl->ssl);
-    rc = X509_digest(srv_crt, digest, (guchar *) base->fingerprint,
-                     &digest_len);
+    rc = X509_digest(srv_crt, digest, digest_bin, &digest_len);
     if ((rc != 0) && (digest_len == EVP_MD_size(digest))) {
-        if (base->expected_fingerprint != NULL) {
-            if (memcmp(base->expected_fingerprint, base->fingerprint,
-                   digest_len) != 0) {
-                if (base->func(ssl,
-                               LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
-                               base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
-                    return FALSE;
-                }
+        _lm_ssl_base_set_fingerprint(base, digest_bin, digest_len);
+        if (_lm_ssl_base_check_fingerprint(base) != 0) {
+            if (base->func(ssl,
+                           LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
+                           base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
+                return FALSE;
             }
         }
     } else {
--- a/loudmouth/lm-ssl.h	Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl.h	Sat Feb 13 12:16:45 2016 +0100
@@ -43,6 +43,9 @@
 #error "Only <loudmouth/loudmouth.h> can be included directly, this file may disappear or change contents."
 #endif
 
+#define LM_FINGERPRINT_PREFIX "SHA256:"
+#define LM_FINGERPRINT_LENGTH 72
+
 G_BEGIN_DECLS
 
 /**