diff --git a/lib/kernel/src/inet_dns_tsig.erl b/lib/kernel/src/inet_dns_tsig.erl index 94ca7f853d88..aa90b1362f2f 100644 --- a/lib/kernel/src/inet_dns_tsig.erl +++ b/lib/kernel/src/inet_dns_tsig.erl @@ -54,18 +54,18 @@ -type tsig_error() :: ?BADSIG | ?BADKEY | ?BADTIME | ?BADTRUNC. -record(tsig_state, { - key :: tsig_key() | list(tsig_key()), - alg :: tsig_alg(), % client only - fudge :: 0..65535, + key :: tsig_key() | list(tsig_key()), + alg :: tsig_alg(), % client only + fudge :: 0..65535, - qr = 0 :: 0..100, % 0 (false): request, 1+ (true): response - % this value is overloaded to handle TSIG - % over TCP where we need to accept up to - % 99 messages without TSIG so each time a - % response with a TSIG RR is received this - % value is reset to 2 - id :: undefined | 0..65535, - mac :: undefined | binary() | crypto:mac_state() + qr = 0 :: 0..100, % 0 (false): request, 1+ (true): response + % this value is overloaded to handle TSIG + % over TCP where we need to accept up to + % 99 messages without TSIG so each time a + % response with a TSIG RR is received this + % value is reset to 2 + id :: undefined | 0..65535, + mac = {?MODULE,undefined} :: {?MODULE,undefined | binary()} | {crypto,crypto:mac_state()} }). -opaque tsig_state() :: #tsig_state{}. -export_type([tsig_state/0]). @@ -135,7 +135,7 @@ sign(Pkt0 = <<_Id:16, QR:1, _:15, _/binary>>, binary:part(Pkt0, {12,byte_size(Pkt0) - 12}), TSigRRB ]), - TS = TS0#tsig_state{ qr = TSQR + 1, mac = MAC }, + TS = TS0#tsig_state{ qr = TSQR + 1, mac = {?MODULE,MAC} }, {ok,Pkt,TS}. % this function needs to work with the original response binary as the MAC @@ -233,7 +233,7 @@ do_verify(Pkt, _Response, TS, TSigRR) -> binary:part(Pkt, {12,Offset - 12}) ]), MACCalc = if - TS#tsig_state.mac == undefined; is_binary(TS#tsig_state.mac) -> + element(1, TS#tsig_state.mac) == ?MODULE -> mac(PktS, TS, Error, Now, OtherData); % RFC8945, section 5.3.1: TSIG on TCP Connections true -> @@ -243,7 +243,7 @@ do_verify(Pkt, _Response, TS, TSigRR) -> % RFC8945, section 5.2 - MUST check time after MAC MAC == MACCalc, NowSigned - Fudge < Now, NowSigned + Fudge > Now -> QR = if TS#tsig_state.qr == 0 -> 1; true -> 2 end, - {ok,TS#tsig_state{ qr = QR, mac = MAC }}; + {ok,TS#tsig_state{ qr = QR, mac = {?MODULE,MAC} }}; MAC == MACCalc -> {error,{notauth,badtime}}; true -> @@ -293,33 +293,33 @@ encode_algname(Alg) -> otherdata(?BADTIME, Now) -> <>; otherdata(_Error, _Now) -> <<>>. -mac0(TS) -> +mac0(TS = #tsig_state{ mac = {?MODULE,MAC} }) -> {_Name,Secret} = TS#tsig_state.key, {Alg,_MACSize} = TS#tsig_state.alg, MACState = crypto:mac_init(hmac, Alg, Secret), - if + {crypto,if % RFC8945, section 5.3.1: TSIG on TCP Connections - is_binary(TS#tsig_state.mac) -> - MS = byte_size(TS#tsig_state.mac), - crypto:mac_update(MACState, [<>, TS#tsig_state.mac]); + is_binary(MAC) -> + MS = byte_size(MAC), + crypto:mac_update(MACState, [<>, MAC]); true -> MACState - end. -macN(Pkt, TS) -> - crypto:mac_update(TS#tsig_state.mac, [ + end}. +macN(Pkt, TS = #tsig_state{ mac = {crypto,MACState} }) -> + {crypto,crypto:mac_update(MACState, [ <<(TS#tsig_state.id):16>>, binary:part(Pkt, {2,byte_size(Pkt) - 2}) - ]). + ])}. % RFC8945, section 5.3.2: Generation of TSIG on Error Returns mac(_TS, Error, _Now, _OtherData) when Error == ?BADSIG; Error == ?BADKEY -> <<>>; -mac(TS, Error, Now, OtherData) -> +mac(TS = #tsig_state{ mac = {crypto,MACState0} }, Error, Now, OtherData) -> {Name,_Secret} = TS#tsig_state.key, {Alg,MACSize} = TS#tsig_state.alg, Fudge = TS#tsig_state.fudge, OtherLen = byte_size(OtherData), - MACState = crypto:mac_update(TS#tsig_state.mac, if + MACState = crypto:mac_update(MACState0, if TS#tsig_state.qr =< 1 -> [ % TSIG RR