--- /dev/null
+package HMLAN_CRYPT;
+
+use Crypt::Rijndael;
+
+sub decrypt(@)
+{
+ my ($self, $ciphertext) = @_;
+ my $plaintext = '';
+
+ while($ciphertext) {
+ if($self->{'keystream'}) {
+ my $len;
+
+ if (length($self->{'keystream'}) > length($ciphertext)) {
+ $len = length($ciphertext);
+ } else {
+ $len = length($self->{'keystream'});
+ }
+
+ my $cpart = substr($ciphertext, 0, $len);
+ my $kpart = substr($self->{'keystream'}, 0, $len);
+
+ $ciphertext = substr($ciphertext, $len);
+ $self->{'keystream'} = substr($self->{'keystream'}, $len);
+
+ $self->{'ciphertext'} .= $cpart;
+
+ $plaintext .= $cpart ^ $kpart;
+ } else {
+ $self->{'keystream'} = $self->{'cipher'}->encrypt($self->{'ciphertext'});
+ $self->{'ciphertext'}='';
+ }
+ }
+
+ $plaintext;
+}
+
+sub encrypt(@)
+{
+ my ($self, $plaintext) = @_;
+ my $ciphertext = '';
+
+ while($plaintext) {
+ if($self->{'keystream'}) {
+ my $len;
+
+ if (length($self->{'keystream'}) > length($plaintext)) {
+ $len = length($plaintext);
+ } else {
+ $len = length($self->{'keystream'});
+ }
+
+ my $ppart = substr($plaintext, 0, $len);
+ my $kpart = substr($self->{'keystream'}, 0, $len);
+
+ $plaintext = substr($plaintext, $len);
+ $self->{'keystream'} = substr($self->{'keystream'}, $len);
+
+ $self->{'ciphertext'} .= $ppart ^ $kpart;
+
+ $ciphertext .= $ppart ^ $kpart;
+ } else {
+ $self->{'keystream'} = $self->{'cipher'}->encrypt($self->{'ciphertext'});
+ $self->{'ciphertext'}='';
+ }
+ }
+
+ $ciphertext;
+}
+
+sub new
+{
+ my $class = shift;
+ my $key = shift;
+ my $iv = shift;
+
+ my $self = {
+ cipher => Crypt::Rijndael->new($key, Crypt::Rijndael::MODE_ECB()),
+ keystream => '',
+ ciphertext => $iv,
+ };
+
+ bless $self, $class;
+}
+
+1;
--- /dev/null
+#!/usr/bin/perl -w
+
+my $key="RUTYOURSECRETHMLANSTICKERKEYHERE";
+my $hmlan="192.168.1.2";
+
+BEGIN {
+ use File::Basename;
+ push @INC, dirname($0);
+}
+
+use HMLAN_CRYPT;
+use IO::Socket::INET;
+use IO::Select;
+
+#This should be random...
+my $my_iv = '00112233445566778899AABBCCDDEEFF';
+my $hmlan_iv = '';
+
+my $sock = IO::Socket::INET->new(
+ PeerAddr => $hmlan,
+ PeerPort => 1000,
+ Proto => 'tcp',
+ Blocking => 0);
+
+my $read_set = new IO::Select();
+$read_set->add($sock);
+
+$read_set->can_read();
+
+chomp(my $iv = <$sock>);
+if ($iv =~ /^V(................................)\r$/) {
+ $hmlan_iv = $1;
+} else {
+ print STDERR "Unknown IV received: ${iv}\n";
+ exit(1);
+}
+
+print $sock "V${my_iv}\r\n";
+
+my $cipher_hmlan=HMLAN_CRYPT->new(pack("H*", $key), pack("H*", $my_iv));
+my $cipher_pc=HMLAN_CRYPT->new(pack("H*", $key), pack("H*", $hmlan_iv));
+
+$read_set->add(\*STDIN);
+
+while(1) {
+ my @ready = $read_set->can_read();
+ foreach my $r (@ready) {
+ if ($r == $sock) {
+ while(my $buf=<$r>) {
+ print $cipher_hmlan->decrypt($buf);
+ }
+ } else {
+ my $buf = <$r>;
+ exit(1) if (!$buf);
+
+ print $sock $cipher_pc->encrypt($buf);
+ }
+ }
+}