[erlang-questions] SSL: Getting master_secret and client_random (or premaster_secret)

Ben Murphy <>
Mon Feb 6 18:48:36 CET 2017


We have a hacky way to do this on R19 (Probably only works for our
particular version because these internal records can change). We
hooked ssl:connect using the tracing facility because we couldn't
deploy a code change.

https://gist.github.com/benmmurphy/d2918d3aaea46372501b851814f4ce8a

DumpMS = fun() ->
     FindMs = fun(Socket) ->
          Pid = element(3, Socket),
          Connection = sys:get_state(Pid),
          State = element(2, Connection),
          Session = element(18, State),
          SessionId = element(2, Session),
          MasterSecret = element(7, Session),
          {SessionId, MasterSecret}
     end,

     Hex = fun(Id) -> << <<Y>> ||<<X:4>> <= Id, Y <-
integer_to_list(X,16)>> end,

     {ok, File} = file:open("/tmp/tls.log", [write, append]),

     DebugHandler = fun DebugHandler() ->

          receive
               {trace, _Pid, return_from, _MFA, {ok, Socket}} ->
                    try
                         {SessionId, MasterSecret} = FindMs(Socket),
                         Bytes =  io_lib:format("RSA Session-ID:~s
Master-Key:~s~n", [Hex(SessionId), Hex(MasterSecret)]),
                         file:write(File, Bytes),
                         ok
                    catch C:E ->
                         ok
                    end,
                    DebugHandler();
               quit ->
                    file:close(File),
                    ok;
               _ ->
                    DebugHandler()
          end,
          ok
     end,


     Pid = spawn(DebugHandler),

     register(ms_tracer, Pid),

     erlang:trace(processes, true, [{tracer, Pid}, call]),

     erlang:trace_pattern({ssl, connect, 2}, [{['_', '_'], [],
[{return_trace}]}]),
     erlang:trace_pattern({ssl, connect, 3}, [{['_', '_', '_'], [],
[{return_trace}]}]),
     erlang:trace_pattern({ssl, connect, 4}, [{['_', '_', '_', '_'],
[], [{return_trace}]}]),

     Pid

end.

QuitMS = fun() ->
     erlang:trace(all, false, [{tracer, whereis(ms_tracer)}, call]),
     ms_tracer ! quit
end.

On Thu, Jan 5, 2017 at 2:20 PM, Roger Lipscombe <> wrote:
> We're using ECDHE and DHE ciphers for our SSL connections. This
> provides perfect forward secrecy, which is good, but it makes it
> impossible to decipher packet captures in wireshark, which is
> expected, and also good, almost all of the time.
>
> Sometimes, however, we *do* need to decipher the traffic.
>
> Note that we own both the client (which is embedded) and the server
> (which uses Erlang -- otherwise I wouldn't be asking here -- and
> ranch). We *could* offer a different cipher suite on the server, which
> would disable PFS, but would do it for all connections. I'd prefer
> something a bit more fine-grained.
>
> You can feed a key log to Wireshark, as documented at
> https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format,
> and it'll correctly decipher the traffic for that connection.
>
> I'd like to find a way to generate a key log file. This requires
> either (client_random, master_secret) or (encrypted_premaster_secret,
> premaster_secret).
>
> Note that I'm looking at the OTP 17.5 source, because that's what we're using.
>
> It would seem that premaster_secret is not stored past the initial
> negotiation, but the client_random and master_secret values are in the
> #security_parameters record in the #connection_state record in the
> #connection_states record, which is in the #state record of the SSL
> connection pid.
>
> But I can't see any (clean) way to retrieve these values, in order to
> generate a key log suitable for Wireshark.
>
> Is there any clean way to do this in OTP 17.5, or is there a supported
> way to do this in OTP 18.x or 19.x?
>
> Regards,
> Roger.
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions


More information about the erlang-questions mailing list