tintinweb / scapy-ssl_tls

SSL/TLS layers for scapy the interactive packet manipulation tool
GNU General Public License v2.0
419 stars 156 forks source link

Allow loading of session secrets directly #64

Open ALSchwalm opened 8 years ago

ALSchwalm commented 8 years ago

Wireshark has an option allowing the user to directly load (pre-)master secrets for decryption. This is useful both because it allows the user to review decrypted traffic captures without having the server's private key available, and also when the cipher suite choice would make it impossible to decrypt the traffic even with the key (i.e., with DH) . Several programs can already generate output in the format wireshark requires, such as firefox and chrome.

This patch adds a function load_secrets_from_file that accepts files in this format. The format is not well documented (the official wireshark docs refer to this stack exchange comment). The format is best described by a comment in the wireshark source here.

If you are interested in merging this, I can add some tests.

tintinweb commented 8 years ago

actually thats a pretty handy extension adding support for NSS Key Log Format logfiles (generic to NSS based applications). Since a sessionctx describes one specific session, would it make sense to have a keystore class that takes care of loading the various formats (rsa, keylog, ..) that provides interfaces to the sessionctx to query for a secret based on the client_random, rsa_pubkey, .... Would probably make the code more readable and move all the key loading stuff to a separate class. what do you think @alexmgr ?

like:

sessionctx.keystore =TLSKeyStore()
sessionctx.keystore.load_rsa(rsa_privkey)
sessionctx.keystore.load_rsa_from_file(path_to_rsa)
sessionctx.keystore.load_keylog(sslkeylogfile)
...
# sessionctx asks keystore for stored privkey or master/premaster-secret
sessionctx.keystore.get_rsa_privkey(pubkey)
sessionctx.keystore.get_master_secret(client_random)
sessionctx.keystore.get_pre_master_secret(client_random)
...
print sessionctx.keystore    # pretty printed output
sessionctx.keystore.save(to_local_file)
sessionctx.keystore.load(from_local_file)
ALSchwalm commented 8 years ago

Oh hey, so that format does have a name. It looks like wireshark uses an extended version (allowing pre-master secrets as well). I can't find any kind of real spec for it. Regardless, I think I'd like to support everything wireshark does.

I like the idea of having a separate keystore type. Are you imagining a custom format for TLSKeyStore.save/load? I'm not aware of a standard format that would encompass the RSA keys as well as the (pre-)master secrets.

alexmgr commented 8 years ago

+2 on this proposal, makes a clear distinction between TLSContext and keys.

We probably want TLSKeyStore properties to be settable only once, when a user specifies the TLSKeyStore explicitely. This would avoid having a whole bunch of conditionals in TLSSessionCtx(), and allow an unconditional set. TLSSessionCtx() and TLSSocket() will also need to have an optional constructor parameter for this key store to allow user override.

@ALSchwalm I believe, what Tin is proposing is an interface for it. Something in this spirit:

class TLSKeyStore(object):
    def save(self, *args, **kwargs):
        raise NotImplementedError()

class RSAKeyStore(TLSKeyStore):
    def save(self, *args, **kwargs):
        do_stuff()
tintinweb commented 8 years ago

https://github.com/tintinweb/scapy-ssl_tls/commit/3b7d12076bb19346d4ef4eecf8ab04dad5c4a666 untested is more or less a braindump of the keystore I had in mind. It is implemented on top of @ALSchwalm changes (thx!).

any thoughts?