]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
enable support for ECC keys and ECDH ciphers. Tested against
authorSander Temme <sctemme@apache.org>
Tue, 10 Nov 2009 07:55:13 +0000 (07:55 +0000)
committerSander Temme <sctemme@apache.org>
Tue, 10 Nov 2009 07:55:13 +0000 (07:55 +0000)
OpenSSL 1.0.0b3.  [Vipul Gupta vipul.gupta sun.com, Sander Temme]

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@834378 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/conf/extra/httpd-ssl.conf.in
modules/ssl/mod_ssl.c
modules/ssl/ssl_engine_init.c
modules/ssl/ssl_engine_kernel.c
modules/ssl/ssl_private.h
modules/ssl/ssl_toolkit_compat.h
modules/ssl/ssl_util.c

diff --git a/CHANGES b/CHANGES
index 0ebac2be3bb135d8286b896eee476dcd5295e686..d74422f7a4ec13cedaa858f983e5104d108dc1a4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,9 @@ Changes with Apache 2.3.3
   *) SECURITY: CVE-2009-3094 (cve.mitre.org)
      mod_proxy_ftp: NULL pointer dereference on error paths.
      [Stefan Fritsch <sf fritsch.de>, Joe Orton]
+     
+  *) mod_ssl: enable support for ECC keys and ECDH ciphers.  Tested against
+     OpenSSL 1.0.0b3.  [Vipul Gupta vipul.gupta sun.com, Sander Temme]
 
   *) mod_dav_fs: Include uri when logging a PUT error due to connection abort.
      PR 38149. [Stefan Fritsch]
index 4ce84263657f50bc74505492811d4e4953b397ae..809ab827d49aa52e7492574ba34e758fa1b89184 100644 (file)
@@ -81,6 +81,9 @@ SSLEngine on
 #   SSL Cipher Suite:
 #   List the ciphers that the client is permitted to negotiate.
 #   See the mod_ssl documentation for a complete list.
+#   Recent OpenSSL snapshots include Elliptic Curve Cryptograhpy (ECC) 
+#   cipher suites (see RFC 4492) as part of "ALL". Edit this line
+#   if you need to disable any of those ciphers.
 SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
 
 #   Server Certificate:
@@ -90,16 +93,22 @@ SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
 #   in mind that if you have both an RSA and a DSA certificate you
 #   can configure both in parallel (to also allow the use of DSA
 #   ciphers, etc.)
+#   Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt)
+#   require an ECC certificate which can also be configured in
+#   parallel.
 SSLCertificateFile "@exp_sysconfdir@/server.crt"
 #SSLCertificateFile "@exp_sysconfdir@/server-dsa.crt"
+#SSLCertificateFile "@exp_sysconfdir@/server-ecc.crt"
 
 #   Server Private Key:
 #   If the key is not combined with the certificate, use this
 #   directive to point at the key file.  Keep in mind that if
 #   you've both a RSA and a DSA private key you can configure
 #   both in parallel (to also allow the use of DSA ciphers, etc.)
+#   ECC keys, when in use, can also be configured in parallel
 SSLCertificateKeyFile "@exp_sysconfdir@/server.key"
 #SSLCertificateKeyFile "@exp_sysconfdir@/server-dsa.key"
+#SSLCertificateKeyFile "@exp_sysconfdir@/server-ecc.key"
 
 #   Server Certificate Chain:
 #   Point SSLCertificateChainFile at a file containing the
index 14a2fd683b4beddc0ed89ab94d69fb22f38ef5c9..af79b37710a06772176d2368d47e22636d0853f7 100644 (file)
@@ -440,6 +440,9 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
      */
     SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
     SSL_set_tmp_dh_callback(ssl,  ssl_callback_TmpDH);
+#ifndef OPENSSL_NO_EC
+    SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH);
+#endif
 
     SSL_set_verify_result(ssl, X509_V_OK);
 
index e4e9bb45e9345b50cc68bba15c5e7787a4ebcc34..3b7b019567026e47b52301198039b505e6bc2c37 100644 (file)
@@ -356,7 +356,11 @@ static void ssl_init_server_check(server_rec *s,
      *  Check for problematic re-initializations
      */
     if (mctx->pks->certs[SSL_AIDX_RSA] ||
-        mctx->pks->certs[SSL_AIDX_DSA])
+        mctx->pks->certs[SSL_AIDX_DSA]
+#ifndef OPENSSL_NO_EC
+      || mctx->pks->certs[SSL_AIDX_ECC]
+#endif
+        )
     {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                 "Illegal attempt to re-initialise SSL for server "
@@ -519,6 +523,9 @@ static void ssl_init_ctx_callbacks(server_rec *s,
 
     SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
     SSL_CTX_set_tmp_dh_callback(ctx,  ssl_callback_TmpDH);
+#ifndef OPENSSL_NO_EC
+    SSL_CTX_set_tmp_ecdh_callback(ctx,ssl_callback_TmpECDH);
+#endif
 
     SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
 }
@@ -810,9 +817,16 @@ static int ssl_server_import_key(server_rec *s,
     ssl_asn1_t *asn1;
     MODSSL_D2I_PrivateKey_CONST unsigned char *ptr;
     const char *type = ssl_asn1_keystr(idx);
-    int pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA;
+    int pkey_type;
     EVP_PKEY *pkey;
 
+#ifndef OPENSSL_NO_EC
+    if (idx == SSL_AIDX_ECC)
+      pkey_type = EVP_PKEY_EC;
+    else
+#endif /* SSL_LIBRARY_VERSION */
+    pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA;
+
     if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, id))) {
         return FALSE;
     }
@@ -922,20 +936,34 @@ static void ssl_init_server_certs(server_rec *s,
                                   apr_pool_t *ptemp,
                                   modssl_ctx_t *mctx)
 {
-    const char *rsa_id, *dsa_id;
+    const char *rsa_id, *dsa_id, *ecc_id;
     const char *vhost_id = mctx->sc->vhost_id;
     int i;
-    int have_rsa, have_dsa;
+    int have_rsa, have_dsa, have_ecc;
 
     rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA);
     dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA);
+#ifndef OPENSSL_NO_EC
+    ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC);
+#endif
 
     have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA);
     have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA);
+#ifndef OPENSSL_NO_EC
+    have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC);
+#endif
 
-    if (!(have_rsa || have_dsa)) {
+    if (!(have_rsa || have_dsa
+#ifndef OPENSSL_NO_EC
+        || have_ecc
+#endif
+)) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+#ifndef OPENSSL_NO_EC
+                "Oops, no RSA, DSA or ECC server certificate found "
+#else
                 "Oops, no RSA or DSA server certificate found "
+#endif
                 "for '%s:%d'?!", s->server_hostname, s->port);
         ssl_die();
     }
@@ -946,10 +974,21 @@ static void ssl_init_server_certs(server_rec *s,
 
     have_rsa = ssl_server_import_key(s, mctx, rsa_id, SSL_AIDX_RSA);
     have_dsa = ssl_server_import_key(s, mctx, dsa_id, SSL_AIDX_DSA);
+#if SSL_LIBRARY_VERSION >= 0x00908000
+    have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC);
+#endif
 
-    if (!(have_rsa || have_dsa)) {
+    if (!(have_rsa || have_dsa
+#if SSL_LIBRARY_VERSION >= 0x00908000
+        || have_ecc
+#endif
+          )) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+#if SSL_LIBRARY_VERSION >= 0x00908000
+                "Oops, no RSA, DSA or ECC server private key found?!");
+#else
                 "Oops, no RSA or DSA server private key found?!");
+#endif
         ssl_die();
     }
 }
index 52bc0a8f5455df48e049a7d3a185f1be115841f8..1249bd1505d29aca88b0a55ef0cd55929544c421 100644 (file)
@@ -1244,6 +1244,33 @@ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
     return (DH *)mc->pTmpKeys[idx];
 }
 
+#ifndef OPENSSL_NO_EC
+EC_KEY *ssl_callback_TmpECDH(SSL *ssl, int export, int keylen)
+{
+    conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
+    SSLModConfigRec *mc = myModConfig(c->base_server);
+    int idx;
+    static EC_KEY *ecdh = NULL;
+    static init = 0;
+
+    /* XXX Uses 256-bit key for now. TODO: support other sizes. */
+    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
+                  "handing out temporary 256 bit ECC key");
+
+    if (init == 0) {
+        ecdh = EC_KEY_new();
+        if (ecdh != NULL) {
+            /* ecdh->group = EC_GROUP_new_by_nid(NID_secp160r2); */
+            EC_KEY_set_group(ecdh, 
+              EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+        }
+        init = 1;
+    }
+    
+    return ecdh;
+}
+#endif
+
 /*
  * This OpenSSL callback function is called when OpenSSL
  * does client authentication and verifies the certificate chain.
index b3b053fc0f930937517a562052ef82760f3442b3..cf9b9278e511e182ba437294e8c3a1917238a485 100644 (file)
@@ -172,11 +172,21 @@ typedef int ssl_algo_t;
 #define SSL_ALGO_UNKNOWN (0)
 #define SSL_ALGO_RSA     (1<<0)
 #define SSL_ALGO_DSA     (1<<1)
+#ifndef OPENSSL_NO_EC
+#define SSL_ALGO_ECC     (1<<2)
+#define SSL_ALGO_ALL     (SSL_ALGO_RSA|SSL_ALGO_DSA|SSL_ALGO_ECC)
+#else
 #define SSL_ALGO_ALL     (SSL_ALGO_RSA|SSL_ALGO_DSA)
+#endif /* SSL_LIBRARY_VERSION */
 
 #define SSL_AIDX_RSA     (0)
 #define SSL_AIDX_DSA     (1)
+#ifndef OPENSSL_NO_EC
+#define SSL_AIDX_ECC     (2)
+#define SSL_AIDX_MAX     (3)
+#else
 #define SSL_AIDX_MAX     (2)
+#endif /* SSL_LIBRARY_VERSION */
 
 
 /**
@@ -626,6 +636,9 @@ void         ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s);
 /**  OpenSSL callbacks */
 RSA         *ssl_callback_TmpRSA(SSL *, int, int);
 DH          *ssl_callback_TmpDH(SSL *, int, int);
+#ifndef OPENSSL_NO_EC
+EC_KEY      *ssl_callback_TmpECDH(SSL *, int, int);
+#endif /* SSL_LIBRARY_VERSION */
 int          ssl_callback_SSLVerify(int, X509_STORE_CTX *);
 int          ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, conn_rec *);
 int          ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP_PKEY **pkey);
index 86a62e8c082eb7eca9351fd4710052bf5788a621..ec0ec856ea875df3282f35c1a1660d0f0eb7fc3a 100644 (file)
 #include <openssl/ocsp.h>
 #endif
 
+/* ECC support came along in OpenSSL 1.0.0 */
+#if (OPENSSL_VERSION_NUMBER < 0x10000000)
+#define OPENSSL_NO_EC
+#endif
+
 /** Avoid tripping over an engine build installed globally and detected
  * when the user points at an explicit non-engine flavor of OpenSSL
  */
index 27c035144f06eb6049cedc13df40f37b3541227a..bdd5a88f1809fab839a82deb6923dbf2277bb438 100644 (file)
@@ -150,6 +150,11 @@ ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey)
             case EVP_PKEY_DSA:
                 t = SSL_ALGO_DSA;
                 break;
+#ifndef OPENSSL_NO_EC
+            case EVP_PKEY_EC:
+                t = SSL_ALGO_ECC;
+                break;
+#endif 
             default:
                 break;
         }
@@ -174,6 +179,11 @@ char *ssl_util_algotypestr(ssl_algo_t t)
         case SSL_ALGO_DSA:
             cp = "DSA";
             break;
+#ifndef OPENSSL_NO_EC
+        case SSL_ALGO_ECC:
+            cp = "ECC";
+            break;
+#endif
         default:
             break;
     }
@@ -245,7 +255,11 @@ void ssl_asn1_table_unset(apr_hash_t *table,
     apr_hash_set(table, key, klen, NULL);
 }
 
+#ifndef OPENSSL_NO_EC
+static const char *ssl_asn1_key_types[] = {"RSA", "DSA", "ECC"};
+#else
 static const char *ssl_asn1_key_types[] = {"RSA", "DSA"};
+#endif
 
 const char *ssl_asn1_keystr(int keytype)
 {