Open ALSchwalm opened 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)
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.
+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()
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!).
TLSKeyStore
is a cookie jar like class to hold multiple TLSSecret
s of different flavor (RSA, MasterSecret, PreMasterSecret, ...)TLSKeyStore
is a class to load any number of supported secrets. It is designed to be somewhat similar to wiresharks ssl secret configuration. Put your secret material and session identification like client_random, encrypted_premaster_secret, server_rsa_pubkey (if available) into TLSKeyStore
and ask TLSKeyStore
to provide the secret for a given session. This may be handy for the session sniffer.TLSKeyStore
reads/writes NSSKeylog style files (with an extension for plain RSA privkeys)any thoughts?
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.