]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
Bitrot: use RSA_generate_key_ex with OpenSSL >= 1.0.0
authorViktor Dukhovni <postfix-users@dukhovni.org>
Thu, 4 Feb 2016 08:38:57 +0000 (03:38 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Thu, 4 Feb 2016 08:38:57 +0000 (03:38 -0500)
postfix/src/tls/tls_rsa.c

index 3e85e19d95d7a46374e8c4e72247ba90ceaa34b3..c440b1e9fc3b8119ca9614fe4347007f290b06cb 100644 (file)
 /*     int     export;
 /*     int     keylength;
 /* DESCRIPTION
-/*     This module maintains parameters for Diffie-Hellman key generation.
-/*
 /*     tls_tmp_rsa_cb() is a call-back routine for the
 /*     SSL_CTX_set_tmp_rsa_callback() function.
+/*
+/*     This implementation will generate only 512-bit ephemeral
+/*     RSA keys for export ciphersuites. It will log a warning in
+/*     all other usage contexts.
 /* LICENSE
 /* .ad
 /* .fi
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Viktor Dukhovni.
 /*--*/
 
 /* System library. */
 
 #include <sys_defs.h>
+#include <msg.h>
 
 #ifdef USE_TLS
 
@@ -47,6 +52,7 @@
 
 #define TLS_INTERNAL
 #include <tls.h>
+#include <openssl/rsa.h>
 
  /*
   * 2015-12-05: Ephemeral RSA removed from OpenSSL 1.1.0-dev
 
 /* tls_tmp_rsa_cb - call-back to generate ephemeral RSA key */
 
-RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int unused_export, int keylength)
+RSA    *tls_tmp_rsa_cb(SSL *unused_ssl, int export, int keylength)
 {
     static RSA *rsa_tmp;
 
-    /* Code adapted from OpenSSL apps/s_cb.c */
+    /*
+     * We generate ephemeral RSA keys only for export ciphersuites.  In all
+     * other contexts use of ephemeral RSA keys violates the SSL/TLS
+     * protocol, and only takes place when applications ask for trouble and
+     * set the SSL_OP_EPHEMERAL_RSA option.  Postfix should never do that.
+     */
+    if (!export || keylength != 512) {
+       msg_warn("%sexport %d-bit ephemeral RSA key requested",
+                export ? "" : "non-", keylength);
+       return 0;
+    }
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+    if (rsa_tmp == 0) {
+       BIGNUM *e = BN_new();
 
+       if (e != 0 && BN_set_word(e, RSA_F4) && (rsa_tmp = RSA_new()) != 0)
+           if (!RSA_generate_key_ex(rsa_tmp, keylength, e, 0)) {
+               RSA_free(rsa_tmp);
+               rsa_tmp = 0;
+           }
+       if (e)
+           BN_free(e);
+    }
+#else
     if (rsa_tmp == 0)
        rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
+#endif
+
     return (rsa_tmp);
 }
-#endif /* OPENSSL_VERSION_NUMBER */
+
+#endif                                 /* OPENSSL_VERSION_NUMBER */
 
 #ifdef TEST
 
-int main(int unused_argc, char **unused_argv)
+#include <msg_vstream.h>
+
+int     main(int unused_argc, char *const argv[])
 {
-    int     ok = 1;
+    int     ok = 0;
+
     /*
      * 2015-12-05: Ephemeral RSA removed from OpenSSL 1.1.0-dev
      */
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
-    ok = ok && tls_tmp_rsa_cb(0, 1, 512) != 0;
-    ok = ok && tls_tmp_rsa_cb(0, 0, 1024) != 0;
-    ok = ok && tls_tmp_rsa_cb(0, 0, 2048) != 0;
+    RSA    *rsa;
+
+    msg_vstream_init(argv[0], VSTREAM_ERR);
+
+    /* Export at 512-bits should work */
+    rsa = tls_tmp_rsa_cb(0, 1, 512);
+    ok = rsa != 0 && RSA_size(rsa) == 512 / 8;
+    ok = ok && PEM_write_RSAPrivateKey(stdout, rsa, 0, 0, 0, 0, 0);
+    tls_print_errors();
+
+    /* Non-export or unexpected bit length should fail */
+    ok = ok && tls_tmp_rsa_cb(0, 0, 512) == 0;
+    ok = ok && tls_tmp_rsa_cb(0, 1, 1024) == 0;
 #endif
 
     return ok ? 0 : 1;