Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Wireshark-dev: Re: [Wireshark-dev] decryption SSL

From: Peter Wu <peter@xxxxxxxxxxxxx>
Date: Mon, 4 Sep 2017 23:05:14 +0100
Hi Sikder,

On Mon, Sep 04, 2017 at 12:48:30PM +0200, Sadik Sikder wrote:
> could you tell me that which part of code decrypts using pre-master
> key log

Have a look at epan/dissectors/packet-ssl.c and
epan/dissectors/packet-ssl-utils.c. For the involved data structures,
see epan/dissectors/packet-ssl-utils.h

The program flow in the common case (SSLv3/TLS) is as follows:

 1. dissect_ssl is the entrypoint (commonly called from TCP dissector).
 2. dissect_ssl3_record is called for each record.
 3. ...which will read the record content type and call functions to
    parse messages including handshake, alerts and application data.
    If data was previously decrypted, that will be reused. Otherwise, an
    record decryption is attempted.
 4. The resulting (decrypted) buffer is given to
    "dissect_ssl3_handshake", "dissect_ssl_payload", etc.

In step 1, a "SslSession" structure is retrieved or created, this stores
information about the current association (connection) like the version
number in use. There is also a "SslDecryptSession" structure which is
created on the first pass(*1) and contains the state necessary to
perform decryption.

 *1) Wireshark can be invoked multiple times for a packet. The first
     time it linearly goes through all packets and performs decryption
     if enough data is available. It may be called again after that to
     fill in columns, or the packet details list (when you select a
     different packet in the GUI).

Decryption requires the cipher to be configured. Trace the use of
SslDecryptSession in the packet-ssl.c and packet-ssl-utils.c files to
find its uses. The "state" field will likely be very helpful. As you may
know, key calculation (https://tools.ietf.org/html/rfc5246#section-6.3)
requires a master secret, a server random and a client random.

In the following sections I will try to describe the process involving
the parameters, the master secret and actual record decryption.

(About Client Random, SSL/TLS Version, Cipher Suite, etc.)
The client and server random values are collected in
"ssl_dissect_hnd_hello_common" (simply follow their call chain to see
how it is invoked). It looks like this:

    ssl_dissect_hnd_hello_common(..., SslDecryptSession *ssl, ...)
    {
        ...
            rnd = &ssl->client_random;
        ...
        tvb_memcpy(tvb, rnd->data, offset, 32);
        ...
            ssl->state |= SSL_CLIENT_RANDOM;

This pattern of saving information during dissection and setting a flag
is used to ensure that all data is available before the decoder
(decryptor) is created.

(About Master Secret)
For RSA cipher suites, the captured Encrypted Premaster Secret can be
decrypted using the RSA private key (see "ssl_decrypt_pre_master_secret"
as used by "ssl_generate_pre_master_secret").

For cipher suites based on a DH key exchange, the captured
ClientKeyExchange and ServerKeyExchange messages are of no use since the
private (typically ephemeral) values are not known. That is why you have
the "keylog file" method which simply maps the Client Random value to
the master secret.

Parsing the keylog file is not that interesting (done by
"ssl_load_keyfile"), but note that it is attempted while parsing the
ChangeCipherSpec message. The motivation is that by now all parameters
(cipher suite, TLS version, Client Random, etc.) should now known and
written to the file. Following this, "ssl_finalize_decryption" is called
in order to try to build a decoder (remember that messages may be
missing in a pcap or that the key may simply be unavailable).

If all parameters are available, "ssl_generate_keyring_material" can
start the real work. It calculates the (pre)master secrets, and then
creates the bidirectional decoders using "ssl_create_decoder".

(Record decryption)
Now that the cipher is setup (the most difficult part I think), it is
time to look at what "decrypt_ssl3_record" does. That function basically
calls "ssl_decrypt_record" to do all the work. To understand function it
is critical that you know about the three encryption types (CBC block
mode, stream encryption and AEAD) as described in
https://tools.ietf.org/html/rfc5246#section-6.2.3

You should read that RFC section in order to navigate this
"ssl_decrypt_record" function. The code has additional references to
RFCs.

I have skipped over details like record compression, fragmentation,
session resumption, extended master secret, export ciphers, TLS 1.3 and
many other things that affect decryption, but hope that this
introduction will be helpful.

Note that the described structure reflects the current implementation as
of Wireshark 2.4. It might not be the best implementation, but should
give you ideas how to write your own one.
-- 
Kind regards,
Peter Wu
https://lekensteyn.nl