mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
TLS decryption: refactoring, more comments, less bare pointers
This commit refactors TLS decryption, adds more comments in scripts and in C++ source-code, and removes use of bare pointers, instead relying more on stl data types.
This commit is contained in:
parent
689b06d9bd
commit
b78f30339f
7 changed files with 186 additions and 120 deletions
|
@ -1,4 +1,10 @@
|
|||
#! Decrypt SSL/TLS payloads
|
||||
##! This script allows for the decryption of certain TLS 1.2 connection, if the user is in possession
|
||||
##! of the private key material for the session. Key material can either be provided via a file (useful
|
||||
##! for processing trace files) or via sending events via broker (for live decoding).
|
||||
##!
|
||||
##! Please note that this feature is experimental and can change without guarantees to our typical
|
||||
##! deprecation tieline. Please also note that currently only TLS 1.2 connections that use the
|
||||
##! TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 cipher suite are supported.
|
||||
|
||||
@load base/frameworks/input
|
||||
@load base/frameworks/notice
|
||||
|
@ -7,49 +13,69 @@
|
|||
|
||||
module SSL;
|
||||
|
||||
export {
|
||||
const keylog_file = getenv("ZEEK_TLS_KEYLOG_FILE") &redef;
|
||||
|
||||
global secrets: table[string] of string = {} &redef;
|
||||
global keys: table[string] of string = {} &redef;
|
||||
|
||||
global add_keys: event(client_random: string, keys: string);
|
||||
|
||||
global add_secret: event(client_random: string, secret: string);
|
||||
}
|
||||
|
||||
# Do not disable analyzers after detection - otherwise we will not receive
|
||||
# encrypted packets.
|
||||
redef SSL::disable_analyzer_after_detection = F;
|
||||
|
||||
export {
|
||||
## This can be set to a file that contains the session secrets for decryption, when parsing a pcap file.
|
||||
## Please note that, when using this feature, you probably want to pause processing of data till this
|
||||
## file has been read.
|
||||
const keylog_file = getenv("ZEEK_TLS_KEYLOG_FILE") &redef;
|
||||
|
||||
## Secrets expire after this time of not being used.
|
||||
const secret_expiration = 5 mins &redef;
|
||||
|
||||
## This event can be triggered, e.g., via broker to add known keys to the TLS key database.
|
||||
##
|
||||
## client_random: client random for which the key is set
|
||||
##
|
||||
## keys: key material
|
||||
global add_keys: event(client_random: string, keys: string);
|
||||
|
||||
## This event can be triggered, e.g., via broker to add known secrets to the TLS secret datbase.
|
||||
##
|
||||
## client_random: client random for which the secret is set
|
||||
##
|
||||
## secrets: derived TLS secrets material
|
||||
global add_secret: event(client_random: string, secret: string);
|
||||
}
|
||||
|
||||
@if ( keylog_file == "" )
|
||||
# If a keylog file was given via an environment variable, let's disable secret expiration - that does not
|
||||
# make sense for pcaps.
|
||||
global secrets: table[string] of string = {} &redef;
|
||||
global keys: table[string] of string = {} &redef;
|
||||
@else
|
||||
#global secrets: table[string] of string = {} &read_expire=secret_expiration &redef;
|
||||
#global keys: table[string] of string = {} &read_expire=secret_expiration &redef;
|
||||
@endif
|
||||
|
||||
|
||||
redef record SSL::Info += {
|
||||
# Decryption uses client_random as identifier
|
||||
client_random: string &log &optional;
|
||||
client_random: string &optional;
|
||||
};
|
||||
|
||||
type Idx: record {
|
||||
type SecretsIdx: record {
|
||||
client_random: string;
|
||||
};
|
||||
|
||||
type Val: record {
|
||||
type SecretsVal: record {
|
||||
secret: string;
|
||||
};
|
||||
|
||||
const input_stream_name = "input-tls-keylog-file";
|
||||
const tls_decrypt_stream_name = "tls-keylog-file";
|
||||
|
||||
event zeek_init()
|
||||
{
|
||||
# listen for secrets
|
||||
Broker::subscribe("/zeek/tls/decryption");
|
||||
|
||||
# FIXME: is such a functionality helpful?
|
||||
# ingest keylog file if the environment is set
|
||||
if ( keylog_file != "" )
|
||||
{
|
||||
suspend_processing();
|
||||
|
||||
Input::add_table([$name=input_stream_name, $source=keylog_file, $destination=secrets, $idx=Idx, $val=Val, $want_record=F]);
|
||||
Input::remove(input_stream_name);
|
||||
Input::add_table([$name=tls_decrypt_stream_name, $source=keylog_file, $destination=secrets, $idx=SecretsIdx, $val=SecretsVal, $want_record=F]);
|
||||
Input::remove(tls_decrypt_stream_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,6 +92,7 @@ event SSL::add_secret(client_random: string, val: string)
|
|||
event ssl_client_hello(c: connection, version: count, record_version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec, comp_methods: index_vec)
|
||||
{
|
||||
c$ssl$client_random = client_random;
|
||||
print "Client random!";
|
||||
|
||||
if ( client_random in keys )
|
||||
set_keys(c, keys[client_random]);
|
||||
|
@ -73,7 +100,7 @@ event ssl_client_hello(c: connection, version: count, record_version: count, pos
|
|||
set_secret(c, secrets[client_random]);
|
||||
}
|
||||
|
||||
event ssl_encrypted_data(c: connection, is_orig: bool, record_version: count, content_type: count, length: count)
|
||||
event ssl_change_cipher_spec(c: connection, is_orig: bool)
|
||||
{
|
||||
if ( c$ssl?$client_random )
|
||||
{
|
||||
|
@ -81,20 +108,5 @@ event ssl_encrypted_data(c: connection, is_orig: bool, record_version: count, co
|
|||
set_keys(c, keys[c$ssl$client_random]);
|
||||
else if ( c$ssl$client_random in secrets )
|
||||
set_secret(c, secrets[c$ssl$client_random]);
|
||||
else
|
||||
{
|
||||
# FIXME: perhaps report that we could not decrypt the session
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event SSL::tls_input_done()
|
||||
{
|
||||
continue_processing();
|
||||
}
|
||||
|
||||
event Input::end_of_data(name: string, source: string)
|
||||
{
|
||||
if ( name == input_stream_name )
|
||||
event SSL::tls_input_done();
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
@load protocols/ssh/geo-data.zeek
|
||||
@load protocols/ssh/interesting-hostnames.zeek
|
||||
@load protocols/ssh/software.zeek
|
||||
#@load protocols/ssl/decryption.zeek
|
||||
@load protocols/ssl/decryption.zeek
|
||||
@load protocols/ssl/expiring-certs.zeek
|
||||
# @load protocols/ssl/extract-certs-pem.zeek
|
||||
@load protocols/ssl/heartbleed.zeek
|
||||
|
|
|
@ -26,11 +26,14 @@ namespace zeek::analyzer::ssl
|
|||
#define MSB(a) ((a >> 8) & 0xff)
|
||||
#define LSB(a) (a & 0xff)
|
||||
|
||||
static void fmt_seq(uint32_t num, u_char* buf)
|
||||
static std::basic_string<unsigned char> fmt_seq(uint32_t num)
|
||||
{
|
||||
memset(buf, 0, 8);
|
||||
std::basic_string<unsigned char> out(4, '\0');
|
||||
out.reserve(13);
|
||||
uint32_t netnum = htonl(num);
|
||||
memcpy(buf + 4, &netnum, 4);
|
||||
out.append(reinterpret_cast<u_char*>(&netnum), 4);
|
||||
out.append(5, '\0');
|
||||
return out;
|
||||
}
|
||||
|
||||
SSL_Analyzer::SSL_Analyzer(Connection* c) : analyzer::tcp::TCP_ApplicationAnalyzer("SSL", c)
|
||||
|
@ -124,9 +127,9 @@ void SSL_Analyzer::Undelivered(uint64_t seq, int len, bool orig)
|
|||
interp->NewGap(orig, len);
|
||||
}
|
||||
|
||||
void SSL_Analyzer::SetSecret(zeek::StringVal* secret)
|
||||
void SSL_Analyzer::SetSecret(const zeek::StringVal& secret)
|
||||
{
|
||||
SetSecret(secret->Len(), secret->Bytes());
|
||||
SetSecret(secret.Len(), secret.Bytes());
|
||||
}
|
||||
|
||||
void SSL_Analyzer::SetSecret(size_t len, const u_char* data)
|
||||
|
@ -135,11 +138,11 @@ void SSL_Analyzer::SetSecret(size_t len, const u_char* data)
|
|||
secret.append((const char*)data, len);
|
||||
}
|
||||
|
||||
void SSL_Analyzer::SetKeys(zeek::StringVal* nkeys)
|
||||
void SSL_Analyzer::SetKeys(const zeek::StringVal& nkeys)
|
||||
{
|
||||
keys.clear();
|
||||
keys.reserve(nkeys->Len());
|
||||
std::copy(nkeys->Bytes(), nkeys->Bytes() + nkeys->Len(), std::back_inserter(keys));
|
||||
keys.reserve(nkeys.Len());
|
||||
std::copy(nkeys.Bytes(), nkeys.Bytes() + nkeys.Len(), std::back_inserter(keys));
|
||||
}
|
||||
|
||||
void SSL_Analyzer::SetKeys(const std::vector<u_char> newkeys)
|
||||
|
@ -282,40 +285,38 @@ bool SSL_Analyzer::TryDecryptApplicationData(int len, const u_char* data, bool i
|
|||
// FIXME: could also print keys or conn id here
|
||||
DBG_LOG(DBG_ANALYZER, "Decrypting application data");
|
||||
|
||||
// NOTE: you must not call functions that invalidate keys.data() on keys during the
|
||||
// remainder of this function. (Given that we do not manipulate the key material in this
|
||||
// function that should not be hard)
|
||||
|
||||
// client write_key
|
||||
u_char c_wk[32];
|
||||
const u_char* c_wk = keys.data();
|
||||
// server write_key
|
||||
u_char s_wk[32];
|
||||
const u_char* s_wk = keys.data() + 32;
|
||||
// client IV
|
||||
u_char c_iv[4];
|
||||
const u_char* c_iv = keys.data() + 64;
|
||||
// server IV
|
||||
u_char s_iv[4];
|
||||
|
||||
// AEAD nonce & tag
|
||||
u_char s_aead_nonce[12];
|
||||
u_char s_aead_tag[13];
|
||||
|
||||
// FIXME: there should be a better way to do these copies
|
||||
memcpy(c_wk, keys.data(), 32);
|
||||
memcpy(s_wk, keys.data() + 32, 32);
|
||||
memcpy(c_iv, keys.data() + 64, 4);
|
||||
memcpy(s_iv, keys.data() + 68, 4);
|
||||
const u_char* s_iv = keys.data() + 68;
|
||||
|
||||
// FIXME: should we change types here?
|
||||
u_char* encrypted = (u_char*)data;
|
||||
size_t encrypted_len = len;
|
||||
|
||||
// FIXME: should this be moved to SSL_Conn?
|
||||
if ( is_orig )
|
||||
c_seq++;
|
||||
else
|
||||
s_seq++;
|
||||
|
||||
// AEAD nonce, length 12
|
||||
std::basic_string<unsigned char> s_aead_nonce;
|
||||
if ( is_orig )
|
||||
memcpy(s_aead_nonce, c_iv, 4);
|
||||
s_aead_nonce.assign(c_iv, 4);
|
||||
else
|
||||
memcpy(s_aead_nonce, s_iv, 4);
|
||||
memcpy(&(s_aead_nonce[4]), encrypted, 8);
|
||||
s_aead_nonce.assign(s_iv, 4);
|
||||
|
||||
// this should be the explicit counter
|
||||
s_aead_nonce.append(encrypted, 8);
|
||||
assert(s_aead_nonce.size() == 12);
|
||||
|
||||
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
|
@ -323,47 +324,60 @@ bool SSL_Analyzer::TryDecryptApplicationData(int len, const u_char* data, bool i
|
|||
|
||||
encrypted += 8;
|
||||
// FIXME: is this because of nonce and aead tag?
|
||||
if ( encrypted_len <= (16 + 8) )
|
||||
{
|
||||
DBG_LOG(DBG_ANALYZER, "Invalid encrypted length encountered during TLS decryption");
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
return false;
|
||||
}
|
||||
encrypted_len -= 8;
|
||||
encrypted_len -= 16;
|
||||
|
||||
// FIXME: aes_256_gcm should not be hardcoded here ;)
|
||||
if ( is_orig )
|
||||
EVP_DecryptInit(ctx, EVP_aes_256_gcm(), c_wk, s_aead_nonce);
|
||||
EVP_DecryptInit(ctx, EVP_aes_256_gcm(), c_wk, s_aead_nonce.data());
|
||||
else
|
||||
EVP_DecryptInit(ctx, EVP_aes_256_gcm(), s_wk, s_aead_nonce);
|
||||
EVP_DecryptInit(ctx, EVP_aes_256_gcm(), s_wk, s_aead_nonce.data());
|
||||
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, encrypted + encrypted_len);
|
||||
|
||||
// AEAD tag
|
||||
std::basic_string<unsigned char> s_aead_tag;
|
||||
if ( is_orig )
|
||||
fmt_seq(c_seq, s_aead_tag);
|
||||
s_aead_tag = fmt_seq(c_seq);
|
||||
else
|
||||
fmt_seq(s_seq, s_aead_tag);
|
||||
s_aead_tag = fmt_seq(s_seq);
|
||||
|
||||
s_aead_tag[8] = content_type;
|
||||
s_aead_tag[9] = MSB(raw_tls_version);
|
||||
s_aead_tag[10] = LSB(raw_tls_version);
|
||||
s_aead_tag[11] = MSB(encrypted_len);
|
||||
s_aead_tag[12] = LSB(encrypted_len);
|
||||
assert(s_aead_tag.size() == 13);
|
||||
|
||||
u_char* decrypted = new u_char[encrypted_len];
|
||||
auto decrypted = std::vector<u_char>(
|
||||
encrypted_len +
|
||||
16); // see OpenSSL manpage - 16 is the block size for the supported cipher
|
||||
int decrypted_len = 0;
|
||||
|
||||
EVP_DecryptUpdate(ctx, NULL, &decrypted_len, s_aead_tag, 13);
|
||||
EVP_DecryptUpdate(ctx, decrypted, &decrypted_len, (const u_char*)encrypted, encrypted_len);
|
||||
EVP_DecryptUpdate(ctx, NULL, &decrypted_len, s_aead_tag.data(), s_aead_tag.size());
|
||||
EVP_DecryptUpdate(ctx, decrypted.data(), &decrypted_len, (const u_char*)encrypted,
|
||||
encrypted_len);
|
||||
assert(decrypted_len <= decrypted.size());
|
||||
decrypted.resize(decrypted_len);
|
||||
|
||||
int res = 0;
|
||||
if ( ! (res = EVP_DecryptFinal(ctx, NULL, &res)) )
|
||||
{
|
||||
DBG_LOG(DBG_ANALYZER, "Decryption failed with return code: %d. Invalid key?\n", res);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
delete[] decrypted;
|
||||
return false;
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_ANALYZER, "Successfully decrypted %d bytes.", decrypted_len);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
ForwardDecryptedData(decrypted_len, reinterpret_cast<const u_char*>(decrypted), is_orig);
|
||||
ForwardDecryptedData(decrypted, is_orig);
|
||||
|
||||
delete[] decrypted;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -371,7 +385,7 @@ bool SSL_Analyzer::TryDecryptApplicationData(int len, const u_char* data, bool i
|
|||
return false;
|
||||
}
|
||||
|
||||
void SSL_Analyzer::ForwardDecryptedData(int len, const u_char* data, bool is_orig)
|
||||
void SSL_Analyzer::ForwardDecryptedData(const std::vector<u_char>& data, bool is_orig)
|
||||
{
|
||||
if ( ! pia )
|
||||
{
|
||||
|
@ -383,18 +397,9 @@ void SSL_Analyzer::ForwardDecryptedData(int len, const u_char* data, bool is_ori
|
|||
}
|
||||
else
|
||||
reporter->FatalError("Could not initialize PIA");
|
||||
|
||||
// FIXME: Also statically add HTTP/H2 at the moment.
|
||||
// We should move this bit to scriptland
|
||||
auto http = analyzer_mgr->InstantiateAnalyzer("HTTP", Conn());
|
||||
if ( http )
|
||||
AddChildAnalyzer(http);
|
||||
auto http2 = analyzer_mgr->InstantiateAnalyzer("HTTP2", Conn());
|
||||
if ( http2 )
|
||||
AddChildAnalyzer(http2);
|
||||
}
|
||||
|
||||
ForwardStream(len, data, is_orig);
|
||||
ForwardStream(data.size(), data.data(), is_orig);
|
||||
}
|
||||
|
||||
} // namespace zeek::analyzer::ssl
|
||||
|
|
|
@ -25,6 +25,9 @@ namespace zeek::analyzer::ssl
|
|||
|
||||
class SSL_Analyzer final : public analyzer::tcp::TCP_ApplicationAnalyzer
|
||||
{
|
||||
// let binpac forward encryppted TLS application data to us.
|
||||
friend class binpac::SSL::SSL_Conn;
|
||||
|
||||
public:
|
||||
explicit SSL_Analyzer(Connection* conn);
|
||||
~SSL_Analyzer() override;
|
||||
|
@ -50,14 +53,20 @@ public:
|
|||
* Set the secret that should be used to derive keys for the
|
||||
* connection. (For TLS 1.2 this is the pre-master secret)
|
||||
*
|
||||
* Please note that these functions currently are hardcoded to only work with a single TLS 1.2
|
||||
* cuphersuite (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384).
|
||||
*
|
||||
* @param secret The secret to set
|
||||
*/
|
||||
void SetSecret(StringVal* secret);
|
||||
void SetSecret(const StringVal& secret);
|
||||
|
||||
/**
|
||||
* Set the secret that should be used to derive keys for the
|
||||
* connection. (For TLS 1.2 this is the pre-master secret)
|
||||
*
|
||||
* Please note that these functions currently are hardcoded to only work with a single TLS 1.2
|
||||
* cuphersuite (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384).
|
||||
*
|
||||
* @param len Length of the secret bytes
|
||||
*
|
||||
* @param data Pointer to the secret bytes
|
||||
|
@ -68,24 +77,32 @@ public:
|
|||
* Set the decryption keys that should be used to decrypt
|
||||
* TLS application data in the connection.
|
||||
*
|
||||
* Please note that these functions currently are hardcoded to only work with a single TLS 1.2
|
||||
* cuphersuite (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384).
|
||||
*
|
||||
* @param keys The key buffer as derived via TLS PRF (for
|
||||
* AES_GCM this should be 72 bytes in length)
|
||||
*/
|
||||
void SetKeys(StringVal* keys);
|
||||
void SetKeys(const StringVal& keys);
|
||||
|
||||
/**
|
||||
* Set the decryption keys that should be used to decrypt
|
||||
* TLS application data in the connection.
|
||||
*
|
||||
* @param len Length of the key buffer (for AES_GCM this should
|
||||
* be 72)
|
||||
* Please note that these functions currently are hardcoded to only work with a single TLS 1.2
|
||||
* cuphersuite (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384).
|
||||
*
|
||||
* @param data Pointer to the key buffer as derived via TLS PRF
|
||||
* @param keys The key buffer as derived via TLS PRF (for
|
||||
* AES_GCM this should be 72 bytes in length)
|
||||
*/
|
||||
void SetKeys(const std::vector<u_char> newkeys);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Try to decrypt TLS application data from a packet. Requires secret or keys to be set prior
|
||||
* Try to decrypt TLS application data from a packet. Requires secret or keys to be set prior.
|
||||
*
|
||||
* Please note that these functions currently are hardcoded to only work with a single TLS 1.2
|
||||
* cuphersuite (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384).
|
||||
*
|
||||
* @param len Length of the encrypted bytes to decrypt
|
||||
*
|
||||
|
@ -96,48 +113,46 @@ public:
|
|||
* @param content_type Content type as given in the TLS packet
|
||||
*
|
||||
* @param raw_tls_version Raw TLS version as given in the TLS packets
|
||||
*
|
||||
* @return True if decryption succeeded and data was forwarded.
|
||||
*/
|
||||
bool TryDecryptApplicationData(int len, const u_char* data, bool is_orig, uint8_t content_type,
|
||||
uint16_t raw_tls_version);
|
||||
|
||||
/**
|
||||
* TLS 1.2 pseudo random function (PRF) used to expand the pre-master secret and derive keys.
|
||||
* The seed is obtained by concatinating rnd1 and rnd2
|
||||
* The seed is obtained by concatinating rnd1 and rnd2.
|
||||
*
|
||||
* Please note that these functions currently are hardcoded to only work with a single TLS 1.2
|
||||
* cuphersuite (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384).
|
||||
*
|
||||
* @param secret Secret as defined in the TLS RFC
|
||||
*
|
||||
* @param label Label as defined in the TLS RFC
|
||||
*
|
||||
* @param rnd1 Pointer to the first part of the seed
|
||||
* @param First part of the seed
|
||||
*
|
||||
* @param rnd1_len Length of the first part of the seed
|
||||
*
|
||||
* @param rnd2 Pointer to the second part of the seed
|
||||
* @param rnd2 Second part of the seed
|
||||
*
|
||||
* @param rnd2_len Length of the second part of the seed
|
||||
*
|
||||
* @param out Pointer to the derived bytes
|
||||
* @param requested_len Length indicating how many bytes should be derived
|
||||
*
|
||||
* @param out_len Length indicating how many bytes should be derived
|
||||
*
|
||||
* @return True, if the operation completed successfully, false otherwise
|
||||
* @return The derived bytes, if the operation succeeds.
|
||||
*/
|
||||
std::optional<std::vector<u_char>> TLS12_PRF(const std::string& secret,
|
||||
const std::string& label, const std::string& rnd1,
|
||||
const std::string& rnd2, size_t requested_len);
|
||||
|
||||
/**
|
||||
* Forward decrypted TLS application data to child analyzers
|
||||
* Forward decrypted TLS application data to child analyzers.
|
||||
*
|
||||
* @param len Length of the data to forward
|
||||
*
|
||||
* @param data Pointer to the data to forward
|
||||
* @param data Data to forward
|
||||
*
|
||||
* @param is_orig Direction of the connection
|
||||
*/
|
||||
void ForwardDecryptedData(int len, const u_char* data, bool is_orig);
|
||||
void ForwardDecryptedData(const std::vector<u_char>& data, bool is_orig);
|
||||
|
||||
protected:
|
||||
binpac::SSL::SSL_Conn* interp;
|
||||
binpac::TLSHandshake::Handshake_Conn* handshake_interp;
|
||||
bool had_gap;
|
||||
|
|
|
@ -9,32 +9,59 @@
|
|||
## finished succesfully).
|
||||
##
|
||||
## c: The SSL connection.
|
||||
function set_ssl_established%(c: connection%): any
|
||||
##
|
||||
## Returns: T on success, F on failure.
|
||||
function set_ssl_established%(c: connection%): bool
|
||||
%{
|
||||
zeek::analyzer::Analyzer* sa = c->FindAnalyzer("SSL");
|
||||
|
||||
if ( sa )
|
||||
{
|
||||
static_cast<zeek::analyzer::ssl::SSL_Analyzer*>(sa)->StartEncryption();
|
||||
return nullptr;
|
||||
return zeek::val_mgr->True();
|
||||
}
|
||||
|
||||
return zeek::val_mgr->False();
|
||||
%}
|
||||
|
||||
## Set the secret that should be used to derive keys for the connection.
|
||||
## (For TLS 1.2 this is the pre-master secret).
|
||||
##
|
||||
## c: The affected connection
|
||||
##
|
||||
## secret: secret to set
|
||||
##
|
||||
## Returns: T on success, F on failure.
|
||||
function set_secret%(c: connection, secret: string%): bool
|
||||
%{
|
||||
analyzer::Analyzer* sa = c->FindAnalyzer("SSL");
|
||||
|
||||
if ( sa )
|
||||
{
|
||||
static_cast<zeek::analyzer::ssl::SSL_Analyzer*>(sa)->SetSecret(secret);
|
||||
{
|
||||
static_cast<zeek::analyzer::ssl::SSL_Analyzer*>(sa)->SetSecret(*secret);
|
||||
return zeek::val_mgr->True();
|
||||
}
|
||||
}
|
||||
|
||||
return zeek::val_mgr->False();
|
||||
%}
|
||||
|
||||
## Set the decryption keys that should be used to decrypt
|
||||
## TLS application data in the connection.
|
||||
##
|
||||
## c: The affected connection
|
||||
##
|
||||
## keys: The key buffer as derived via TLS PRF.
|
||||
##
|
||||
## Returns: T on success, F on failure.
|
||||
function set_keys%(c: connection, keys: string%): bool
|
||||
%{
|
||||
analyzer::Analyzer* sa = c->FindAnalyzer("SSL");
|
||||
|
||||
if ( sa )
|
||||
{
|
||||
static_cast<zeek::analyzer::ssl::SSL_Analyzer*>(sa)->SetKeys(keys);
|
||||
{
|
||||
static_cast<zeek::analyzer::ssl::SSL_Analyzer*>(sa)->SetKeys(*keys);
|
||||
return zeek::val_mgr->True();
|
||||
}
|
||||
}
|
||||
|
||||
return zeek::val_mgr->False();
|
||||
%}
|
||||
|
|
|
@ -13,10 +13,12 @@ refine connection SSL_Conn += {
|
|||
|
||||
%member{
|
||||
int established_;
|
||||
int decryption_failed_;
|
||||
%}
|
||||
|
||||
%init{
|
||||
established_ = false;
|
||||
decryption_failed_ = false;
|
||||
%}
|
||||
|
||||
%cleanup{
|
||||
|
@ -65,10 +67,13 @@ refine connection SSL_Conn += {
|
|||
{
|
||||
zeek::BifEvent::enqueue_ssl_encrypted_data(zeek_analyzer(),
|
||||
zeek_analyzer()->Conn(), ${rec.is_orig}, ${rec.raw_tls_version}, ${rec.content_type}, ${rec.length});
|
||||
if (rec->content_type() == APPLICATION_DATA)
|
||||
{
|
||||
zeek_analyzer()->TryDecryptApplicationData(cont.length(), cont.data(), rec->is_orig(), rec->content_type(), rec->raw_tls_version());
|
||||
}
|
||||
}
|
||||
|
||||
if ( rec->content_type() == APPLICATION_DATA && decryption_failed_ == false )
|
||||
{
|
||||
// If decryption of one packet fails, do not try to decrypt future packets.
|
||||
if ( ! zeek_analyzer()->TryDecryptApplicationData(cont.length(), cont.data(), rec->is_orig(), rec->content_type(), rec->raw_tls_version()) )
|
||||
decryption_failed_ = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
# @TEST-REQUIRES: grep -q "#define OPENSSL_HAVE_KDF_H" $BUILD/zeek-config.h
|
||||
|
||||
# @TEST-EXEC: zeek -b -C -r $TRACES/tls/tls12-decryption.pcap %INPUT
|
||||
# @TEST-EXEC: zeek -B dpd -C -r $TRACES/tls/tls12-decryption.pcap %INPUT
|
||||
# @TEST-EXEC: btest-diff http.log
|
||||
|
||||
@load protocols/ssl/decryption
|
||||
@load base/protocols/http
|
||||
|
||||
module SSL;
|
||||
|
||||
redef SSL::secrets += {
|
||||
["\xb4\x0a\x24\x4b\x48\xe4\x2e\xac\x28\x71\x44\xb1\xb7\x39\x30\x57\xca\xa1\x31\xf9\x61\xa7\x8e\x38\xb0\xe7\x7c\x1e"] = "\xbd\x01\xe5\x89\xd1\x05\x19\x9e\x9a\xb5\xfc\x9b\xd7\x58\xb5\xf2\x88\xdb\x28\xfd\x80\xaa\x02\x26\x1e\x47\x65\xac\x13\x57\xd0\x07\xfd\x08\xc7\xbd\xab\x45\x45\x0e\x01\x5a\x01\xd0\x8e\x5e\x7c\xa6",
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue