Blame SOURCES/IO-Socket-SSL-1.94-Added-support-for-ECDH-key-exchange-with-key-SSL_ecd.patch

a8323a
From 24fa6df5e1910269d86cb97bb5cef464fc3111ca Mon Sep 17 00:00:00 2001
a8323a
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
a8323a
Date: Wed, 19 Mar 2014 12:54:22 +0100
a8323a
Subject: [PATCH] Added support for ECDH key exchange with key SSL_ecdh_curve
a8323a
MIME-Version: 1.0
a8323a
Content-Type: text/plain; charset=UTF-8
a8323a
Content-Transfer-Encoding: 8bit
a8323a
a8323a
This is port of following upstream commit to 1.94 version:
a8323a
a8323a
commit e067e09bf0c6b5844693169af75ec93b22bfa660
a8323a
Author: Steffen Ullrich <Steffen_Ullrich@genua.de>
a8323a
Date:   Fri Oct 11 18:50:01 2013 +0200
a8323a
a8323a
    1.955 - added support for ECDH key exchange with key SSL_ecdh_curve
a8323a
a8323a
Signed-off-by: Petr Písař <ppisar@redhat.com>
a8323a
---
a8323a
 MANIFEST  |  1 +
a8323a
 SSL.pm    | 28 +++++++++++++++++++++++
a8323a
 t/ecdhe.t | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
a8323a
 3 files changed, 107 insertions(+)
a8323a
 create mode 100644 t/ecdhe.t
a8323a
a8323a
diff --git a/MANIFEST b/MANIFEST
a8323a
index afed6c6..3d97511 100644
a8323a
--- a/MANIFEST
a8323a
+++ b/MANIFEST
a8323a
@@ -50,6 +50,7 @@ t/auto_verify_hostname.t
a8323a
 t/verify_hostname.t
a8323a
 t/sni.t
a8323a
 t/mitm.t
a8323a
+t/ecdhe.t
a8323a
 util/export_certs.pl
a8323a
 META.yml                                 Module YAML meta-data (added by MakeMaker)
a8323a
 META.json                                Module JSON meta-data (added by MakeMaker)
a8323a
diff --git a/SSL.pm b/SSL.pm
a8323a
index bcf098f..ad18f7a 100644
a8323a
--- a/lib/IO/Socket/SSL.pm
a8323a
+++ b/lib/IO/Socket/SSL.pm
a8323a
@@ -1756,6 +1756,25 @@ sub new {
a8323a
 	    Net::SSLeay::DH_free( $dh );
a8323a
 	    $rv || return IO::Socket::SSL->error( "Failed to set DH from $f" );
a8323a
 	}
a8323a
+
a8323a
+	if ( my $curve = $arg_hash->{SSL_ecdh_curve} ) {
a8323a
+	    return IO::Socket::SSL->error(
a8323a
+		"ECDH curve needs Net::SSLeay>=1.56 and OpenSSL>=1.0")
a8323a
+		if ! defined( &Net::SSLeay::CTX_set_tmp_ecdh );
a8323a
+	    if ( $curve !~ /^\d+$/ ) {
a8323a
+		# name of curve, find NID
a8323a
+		$curve = Net::SSLeay::OBJ_txt2nid($curve) 
a8323a
+		    || return IO::Socket::SSL->error(
a8323a
+		    "cannot find NID for curve name '$curve'");
a8323a
+	    }
a8323a
+	    my $ecdh = Net::SSLeay::EC_KEY_new_by_curve_name($curve) or 
a8323a
+		return IO::Socket::SSL->error(
a8323a
+		"cannot create curve for NID $curve");
a8323a
+	    Net::SSLeay::CTX_set_tmp_ecdh($ctx,$ecdh) or
a8323a
+		return IO::Socket::SSL->error(
a8323a
+		"failed to set ECDH curve context");
a8323a
+	    Net::SSLeay::EC_KEY_free($ecdh);
a8323a
+	}
a8323a
     }
a8323a
 
a8323a
     my $verify_cb = $arg_hash->{SSL_verify_callback};
a8323a
@@ -2158,11 +2177,20 @@ C<SSL_key> option.
a8323a
 
a8323a
 If you want Diffie-Hellman key exchange you need to supply a suitable file here
a8323a
 or use the SSL_dh parameter. See dhparam command in openssl for more information.
a8323a
+To create a server which provides perfect forward secrecy you need to either
a8323a
+give the DH parameters or (better, because faster) the ECDH curve.
a8323a
 
a8323a
 =item SSL_dh
a8323a
 
a8323a
 Like SSL_dh_file, but instead of giving a file you use a preloaded or generated DH*.
a8323a
 
a8323a
+=item SSL_ecdh_curve
a8323a
+
a8323a
+If you want Elliptic Curve Diffie-Hellmann key exchange you need to supply the
a8323a
+OID or NID of a suitable curve (like 'prime256v1') here.
a8323a
+To create a server which provides perfect forward secrecy you need to either
a8323a
+give the DH parameters or (better, because faster) the ECDH curve.
a8323a
+
a8323a
 =item SSL_passwd_cb
a8323a
 
a8323a
 If your private key is encrypted, you might not want the default password prompt from
a8323a
diff --git a/t/ecdhe.t b/t/ecdhe.t
a8323a
new file mode 100644
a8323a
index 0000000..40aed59
a8323a
--- /dev/null
a8323a
+++ b/t/ecdhe.t
a8323a
@@ -0,0 +1,78 @@
a8323a
+#!perl
a8323a
+# Before `make install' is performed this script should be runnable with
a8323a
+# `make test'. After `make install' it should work as `perl t/ecdhe.t'
a8323a
+
a8323a
+use strict;
a8323a
+use warnings;
a8323a
+use Net::SSLeay;
a8323a
+use Socket;
a8323a
+use IO::Socket::SSL;
a8323a
+
a8323a
+if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) {
a8323a
+    print "1..0 # Skipped: fork not implemented on this platform\n";
a8323a
+    exit
a8323a
+}
a8323a
+
a8323a
+if ( ! defined &Net::SSLeay::CTX_set_tmp_ecdh ) {
a8323a
+    print "1..0 # Skipped: no support for ecdh with this openssl/Net::SSLeay\n";
a8323a
+    exit
a8323a
+}
a8323a
+
a8323a
+$|=1;
a8323a
+print "1..4\n";
a8323a
+
a8323a
+# first create simple ssl-server
a8323a
+my $ID = 'server';
a8323a
+my $addr = '127.0.0.1';
a8323a
+my $server = IO::Socket::SSL->new(
a8323a
+    LocalAddr => $addr,
a8323a
+    Listen => 2,
a8323a
+    ReuseAddr => 1,
a8323a
+    SSL_cert_file => "certs/server-cert.pem",
a8323a
+    SSL_key_file  => "certs/server-key.pem",
a8323a
+    SSL_ecdh_curve => 'prime256v1',
a8323a
+) || do {
a8323a
+    notok($!);
a8323a
+    exit
a8323a
+};
a8323a
+ok("Server Initialization");
a8323a
+
a8323a
+# add server port to addr
a8323a
+$addr.= ':'.(sockaddr_in( getsockname( $server )))[0];
a8323a
+
a8323a
+my $pid = fork();
a8323a
+if ( !defined $pid ) {
a8323a
+    die $!; # fork failed
a8323a
+
a8323a
+} elsif ( !$pid ) {    ###### Client
a8323a
+
a8323a
+    $ID = 'client';
a8323a
+    close($server);
a8323a
+    my $to_server = IO::Socket::SSL->new(
a8323a
+	PeerAddr => $addr,
a8323a
+	SSL_verify_mode => 0 ) || do {
a8323a
+	notok( "connect failed: $SSL_ERROR" );
a8323a
+	exit
a8323a
+    };
a8323a
+    ok( "client connected" );
a8323a
+
a8323a
+    my $cipher = $to_server->get_cipher();
a8323a
+    if ( $cipher !~m/^ECDHE-/ ) {
a8323a
+	notok("bad key exchange: $cipher");
a8323a
+	exit;
a8323a
+    }
a8323a
+    ok("ecdh key exchange: $cipher");
a8323a
+
a8323a
+} else {                ###### Server
a8323a
+
a8323a
+    my $to_client = $server->accept || do {
a8323a
+	notok( "accept failed: $SSL_ERROR" );
a8323a
+	kill(9,$pid);
a8323a
+	exit;
a8323a
+    };
a8323a
+    ok( "Server accepted" );
a8323a
+    wait;
a8323a
+}
a8323a
+
a8323a
+sub ok { print "ok # [$ID] @_\n"; }
a8323a
+sub notok { print "not ok # [$ID] @_\n"; }
a8323a
-- 
a8323a
1.8.5.3
a8323a