diff options
author | Ryan Riske <ryanriske@gmail.com> | 2015-03-01 20:23:07 -0600 |
---|---|---|
committer | Ryan Riske <ryanriske@gmail.com> | 2015-03-01 20:29:10 -0600 |
commit | 7c6c1e2073207612a2d819471bc680564c945cc7 (patch) | |
tree | 57d1ba248feb69146d751c8c788d0091d713ecf2 /lib/Vyatta/VPN | |
parent | 7d94dd6e4d32eef9cea4a4f7270b0ea0d895dd12 (diff) | |
download | vyatta-cfg-vpn-7c6c1e2073207612a2d819471bc680564c945cc7.tar.gz vyatta-cfg-vpn-7c6c1e2073207612a2d819471bc680564c945cc7.zip |
Add support for RSA keys with strongSwan 5.2.x
strongSwan 5.2.x no longer recognizes keys in RFC 3110 format inlined in
ipsec.conf and ipsec.secrets. We need to convert the local private key
and peer public keys to PEM format, without changing the config templates
or user-visible key formats.
This patch will require the Debian packages 'libcrypt-openssl-bignum-perl'
and 'libcrypt-openssl-rsa-perl' to be added to the system.
Diffstat (limited to 'lib/Vyatta/VPN')
-rwxr-xr-x | lib/Vyatta/VPN/Util.pm | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/lib/Vyatta/VPN/Util.pm b/lib/Vyatta/VPN/Util.pm index a40cc90..65877b0 100755 --- a/lib/Vyatta/VPN/Util.pm +++ b/lib/Vyatta/VPN/Util.pm @@ -27,10 +27,14 @@ use strict; use warnings; our @EXPORT = qw(rsa_get_local_key_file LOCAL_KEY_FILE_DEFAULT rsa_get_local_pubkey - is_vpn_running vpn_debug enableICMP is_tcp_udp get_protocols conv_protocol); + rsa_convert_pubkey_pem is_vpn_running vpn_debug enableICMP is_tcp_udp + get_protocols conv_protocol); use base qw(Exporter); use Vyatta::Config; +use Crypt::OpenSSL::RSA; +use MIME::Base64; +use File::Copy; use POSIX qw(strftime); use constant LOCAL_KEY_FILE_DEFAULT @@ -110,15 +114,57 @@ sub rsa_get_local_pubkey { my @raw_data=<$dat>; close($dat); + # PEM encoded private key + my $rsa = Crypt::OpenSSL::RSA->new_private_key(join("", @raw_data)); + if (defined $rsa) { + my ($n, $e) = $rsa->get_key_parameters(); + my $eb = $e->to_bin(); + return "0s" . encode_base64(pack("C", length($eb)) . $eb . $n->to_bin(), ''); + } + + # legacy private key format foreach my $line (@raw_data) { my $file_pubkey; if (($file_pubkey) = ($line =~ m/\s+\#pubkey=(\S+)/)) { + # Found a legacy private key; convert to PEM for strongSwan 5.2.x + my $key = join("", @raw_data); + $key =~ /^\s+Modulus:\s+0x([0-9a-fA-F]+)$/m; + my $n = Crypt::OpenSSL::Bignum->new_from_hex($1); + $key =~ /^\s+PublicExponent:\s+0x([0-9a-fA-F]+)$/m; + my $e = Crypt::OpenSSL::Bignum->new_from_hex($1); + $key =~ /^\s+PrivateExponent:\s+0x([0-9a-fA-F]+)$/m; + my $d = Crypt::OpenSSL::Bignum->new_from_hex($1); + $key =~ /^\s+Prime1:\s+0x([0-9a-fA-F]+)$/m; + my $p = Crypt::OpenSSL::Bignum->new_from_hex($1); + $key =~ /^\s+Prime2:\s+0x([0-9a-fA-F]+)$/m; + my $q = Crypt::OpenSSL::Bignum->new_from_hex($1); + + my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e, $d, $p, $q); + if (defined $rsa) { + # write out PEM formatted key + move("$file", "$file.bak"); + open(my $priv, '>', "$file") + or return 0; + chmod 0600, $file; + print {$priv} $rsa->get_private_key_string(); + close($priv); + } return $file_pubkey; } } return 0; } +sub rsa_convert_pubkey_pem { + my $key = shift; + my $decoded = decode_base64($key); + my $len = unpack("C", substr($decoded, 0, 1)); + my $e = Crypt::OpenSSL::Bignum->new_from_bin(substr($decoded, 1, $len)); + my $n = Crypt::OpenSSL::Bignum->new_from_bin(substr($decoded, 1 + $len)); + my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e); + return $rsa->get_public_key_x509_string(); +} + sub vpn_debug { my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime); |