summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRyan Riske <ryanriske@gmail.com>2015-03-01 20:23:07 -0600
committerRyan Riske <ryanriske@gmail.com>2015-03-01 20:29:10 -0600
commit7c6c1e2073207612a2d819471bc680564c945cc7 (patch)
tree57d1ba248feb69146d751c8c788d0091d713ecf2 /lib
parent7d94dd6e4d32eef9cea4a4f7270b0ea0d895dd12 (diff)
downloadvyatta-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')
-rwxr-xr-xlib/Vyatta/VPN/Util.pm48
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);