… | |
… | |
27 | use Scalar::Util (); |
27 | use Scalar::Util (); |
28 | use List::Util (); |
28 | use List::Util (); |
29 | use MIME::Base64 (); |
29 | use MIME::Base64 (); |
30 | |
30 | |
31 | use JSON::XS (); |
31 | use JSON::XS (); |
32 | use Digest::MD6 (); |
32 | use Digest::SHA3 (); |
33 | use Digest::HMAC_MD6 (); |
33 | use Digest::HMAC (); |
34 | |
34 | |
35 | use AnyEvent (); |
35 | use AnyEvent (); |
36 | use AnyEvent::Socket (); |
36 | use AnyEvent::Socket (); |
37 | use AnyEvent::Handle 4.92 (); |
37 | use AnyEvent::Handle 4.92 (); |
38 | |
38 | |
… | |
… | |
118 | tls_ctx => AnyEvent::TLS, |
118 | tls_ctx => AnyEvent::TLS, |
119 | peername => $peername, # for verification |
119 | peername => $peername, # for verification |
120 | ; |
120 | ; |
121 | |
121 | |
122 | =cut |
122 | =cut |
|
|
123 | |
|
|
124 | sub hmac_sha3_512_hex($$) { |
|
|
125 | Digest::HMAC::hmac_hex $_[1], $_[0], \&Digest::SHA3::sha3_512, 72 |
|
|
126 | } |
123 | |
127 | |
124 | sub new { |
128 | sub new { |
125 | my ($class, %arg) = @_; |
129 | my ($class, %arg) = @_; |
126 | |
130 | |
127 | my $self = bless \%arg, $class; |
131 | my $self = bless \%arg, $class; |
… | |
… | |
254 | } |
258 | } |
255 | |
259 | |
256 | defined $s_framing |
260 | defined $s_framing |
257 | or return $self->error ("$framings: no common framing method supported"); |
261 | or return $self->error ("$framings: no common framing method supported"); |
258 | |
262 | |
259 | my $key; |
|
|
260 | my $lauth; |
263 | my $lauth; |
261 | |
264 | |
262 | if ($tls) { |
265 | if ($tls) { |
263 | $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept"; |
266 | $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept"; |
264 | $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); |
267 | $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); |
265 | return unless $self->{hdl}; # starttls might destruct us |
268 | return unless $self->{hdl}; # starttls might destruct us |
266 | |
269 | |
267 | $lauth = |
270 | $lauth = |
268 | $s_auth eq "tls_anon" ? "" |
271 | $s_auth eq "tls_anon" ? "" |
269 | : $s_auth eq "tls_md6_64_256" ? Digest::MD6::md6_hex "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012" |
272 | : $s_auth eq "tls_sha3_512" ? Digest::SHA3::sha3_512_hex "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012" |
270 | : return $self->error ("$s_auth: fatal, selected unsupported snd auth method"); |
273 | : return $self->error ("$s_auth: fatal, selected unsupported snd auth method"); |
271 | |
274 | |
272 | } elsif (length $secret) { |
275 | } elsif (length $secret) { |
273 | return $self->error ("$s_auth: fatal, selected unsupported snd auth method") |
276 | return $self->error ("$s_auth: fatal, selected unsupported snd auth method") |
274 | unless $s_auth eq "hmac_md6_64_256"; # hardcoded atm. |
277 | unless $s_auth eq "hmac_sha3_512"; # hardcoded atm. |
275 | |
278 | |
276 | $key = Digest::MD6::md6 $secret; |
|
|
277 | # we currently only support hmac_md6_64_256 |
|
|
278 | $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256; |
279 | $lauth = hmac_sha3_512_hex $secret, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012"; |
279 | |
280 | |
280 | } else { |
281 | } else { |
281 | return $self->error ("unable to handshake TLS and no shared secret configured"); |
282 | return $self->error ("unable to handshake TLS and no shared secret configured"); |
282 | } |
283 | } |
283 | |
284 | |
… | |
… | |
289 | my ($hdl, $rline) = @_; |
290 | my ($hdl, $rline) = @_; |
290 | |
291 | |
291 | my ($auth_method, $rauth2, $r_framing) = split /;/, $rline; |
292 | my ($auth_method, $rauth2, $r_framing) = split /;/, $rline; |
292 | |
293 | |
293 | my $rauth = |
294 | my $rauth = |
294 | $auth_method eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_hex $key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256 |
295 | $auth_method eq "hmac_sha3_512" ? hmac_sha3_512_hex $secret, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012" |
295 | : $auth_method eq "cleartext" ? unpack "H*", $secret |
296 | : $auth_method eq "cleartext" ? unpack "H*", $secret |
296 | : $auth_method eq "tls_anon" ? ($tls ? "" : "\012\012") # \012\012 never matches |
297 | : $auth_method eq "tls_anon" ? ($tls ? "" : "\012\012") # \012\012 never matches |
297 | : $auth_method eq "tls_md6_64_256" ? ($tls ? Digest::MD6::md6_hex "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012" : "\012\012") |
298 | : $auth_method eq "tls_sha3_512" ? ($tls ? Digest::SHA3::sha3_512_hex "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012" : "\012\012") |
298 | : return $self->error ("$auth_method: fatal, selected unsupported rcv auth method"); |
299 | : return $self->error ("$auth_method: fatal, selected unsupported rcv auth method"); |
299 | |
300 | |
300 | if ($rauth2 ne $rauth) { |
301 | if ($rauth2 ne $rauth) { |
301 | return $self->error ("authentication failure/shared secret mismatch"); |
302 | return $self->error ("authentication failure/shared secret mismatch"); |
302 | } |
303 | } |
… | |
… | |
612 | This is simply the shared secret, lowercase-hex-encoded. This method is of |
613 | This is simply the shared secret, lowercase-hex-encoded. This method is of |
613 | course very insecure if TLS is not used (and not completely secure even |
614 | course very insecure if TLS is not used (and not completely secure even |
614 | if TLS is used), which is why this module will accept, but not generate, |
615 | if TLS is used), which is why this module will accept, but not generate, |
615 | cleartext auth replies. |
616 | cleartext auth replies. |
616 | |
617 | |
617 | =item hmac_md6_64_256 |
618 | =item hmac_sha3_512 |
618 | |
619 | |
619 | This method uses an MD6 HMAC with 64 bit blocksize and 256 bit hash, and |
620 | This method uses a SHA-3/512 HMAC with 576 bit blocksize and 512 bit hash, |
620 | requires a shared secret. It is the preferred auth method when a shared |
621 | and requires a shared secret. It is the preferred auth method when a |
621 | secret is available. |
622 | shared secret is available. |
622 | |
623 | |
623 | First, the shared secret is hashed with MD6: |
|
|
624 | |
|
|
625 | key = MD6 (secret) |
|
|
626 | |
|
|
627 | This secret is then used to generate the "local auth reply", by taking |
624 | The secret is used to generate the "local auth reply", by taking the |
628 | the two local greeting lines and the two remote greeting lines (without |
625 | two local greeting lines and the two remote greeting lines (without |
629 | line endings), appending \012 to all of them, concatenating them and |
626 | line endings), appending \012 to all of them, concatenating them and |
630 | calculating the MD6 HMAC with the key: |
627 | calculating the HMAC with the key: |
631 | |
628 | |
632 | lauth = HMAC_MD6 key, "lgreeting1\012lgreeting2\012rgreeting1\012rgreeting2\012" |
629 | lauth = HMAC_SHA3_512 key, "lgreeting1\012lgreeting2\012rgreeting1\012rgreeting2\012" |
633 | |
630 | |
634 | This authentication token is then lowercase-hex-encoded and sent to the |
631 | This authentication token is then lowercase-hex-encoded and sent to the |
635 | other side. |
632 | other side. |
636 | |
633 | |
637 | Then the remote auth reply is generated using the same method, but local |
634 | Then the remote auth reply is generated using the same method, but local |
638 | and remote greeting lines swapped: |
635 | and remote greeting lines swapped: |
639 | |
636 | |
640 | rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" |
637 | rauth = HMAC_SHA3_512 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" |
641 | |
638 | |
642 | This is the token that is expected from the other side. |
639 | This is the token that is expected from the other side. |
|
|
640 | |
|
|
641 | =item hmac_md6_64_256 [obsolete, not supported] |
|
|
642 | |
|
|
643 | This method uses an MD6 HMAC with 64 bit blocksize and 256 bit hash, and |
|
|
644 | requires a shared secret. It is similar to C<hmac_sha3_512>, but uses |
|
|
645 | MD6 instead of SHA-3 and instead of using the secret directly, it uses |
|
|
646 | MD6(secret) as HMAC key. |
643 | |
647 | |
644 | =item tls_anon |
648 | =item tls_anon |
645 | |
649 | |
646 | This type is only valid I<iff> TLS was enabled and the TLS handshake |
650 | This type is only valid I<iff> TLS was enabled and the TLS handshake |
647 | was successful. It has no authentication data, as the server/client |
651 | was successful. It has no authentication data, as the server/client |
… | |
… | |
653 | exploits this in a way that is worse than just denying the service. |
657 | exploits this in a way that is worse than just denying the service. |
654 | |
658 | |
655 | By default, this implementation accepts but never generates this auth |
659 | By default, this implementation accepts but never generates this auth |
656 | reply. |
660 | reply. |
657 | |
661 | |
658 | =item tls_md6_64_256 |
662 | =item tls_sha3_512 |
659 | |
663 | |
660 | This type is only valid I<iff> TLS was enabled and the TLS handshake was |
664 | This type is only valid I<iff> TLS was enabled and the TLS handshake was |
661 | successful. |
665 | successful. |
662 | |
666 | |
663 | This authentication type simply calculates: |
667 | This authentication type simply calculates: |
664 | |
668 | |
665 | lauth = MD6 "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" |
669 | lauth = SHA3_512 "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" |
666 | |
670 | |
667 | and lowercase-hex encodes the result and sends it as authentication |
671 | and lowercase-hex encodes the result and sends it as authentication |
668 | data. No shared secret is required (authentication is done by TLS). The |
672 | data. No shared secret is required (authentication is done by TLS). The |
669 | checksum exists only to make tinkering with the greeting hard. |
673 | checksum exists only to make tinkering with the greeting hard. |
|
|
674 | |
|
|
675 | =item tls_md6_64_256 [deprecated, unsupported] |
|
|
676 | |
|
|
677 | Same as C<tls_sha3_512>, except MD6 is used. |
670 | |
678 | |
671 | =back |
679 | =back |
672 | |
680 | |
673 | =item the authentication data |
681 | =item the authentication data |
674 | |
682 | |
… | |
… | |
726 | check the authenticity of the other side and use cleartext authentication |
734 | check the authenticity of the other side and use cleartext authentication |
727 | yourself. The the handshake is as simple as sending three lines of text, |
735 | yourself. The the handshake is as simple as sending three lines of text, |
728 | reading three lines of text, and then you can exchange JSON-formatted |
736 | reading three lines of text, and then you can exchange JSON-formatted |
729 | messages: |
737 | messages: |
730 | |
738 | |
731 | aemp;1;<nodename>;hmac_md6_64_256;json |
739 | aemp;1;<nodename>;hmac_sha3_512;json |
732 | <nonce> |
740 | <nonce> |
733 | cleartext;<hexencoded secret>;json |
741 | cleartext;<hexencoded secret>;json |
734 | |
742 | |
735 | The nodename should be unique within the network, preferably unique with |
743 | The nodename should be unique within the network, preferably unique with |
736 | every connection, the <nonce> could be empty or some random data, and the |
744 | every connection, the <nonce> could be empty or some random data, and the |