1
1
mirror of https://github.com/wader/fq.git synced 2024-12-29 00:22:38 +03:00
fq/format/tls/tlsdecrypt/tlsdecrypt.go
Mattias Wadman 9852f56b74 tls: Add TLS 1.0, 1.1, 1.2 decode and decryption
What it can do:
- Decodes records and most standard messages and extensions.
- Decryptes records and reassemples application data stream if a keylog is provided
  and the cipher suite is supported.
- Supports most recommended and used ciphers and a bunch of older ones.

What it can't do:
- SSL v3 maybe supported, is similar to TLS 1.0, not tested.
- Decryption and renegotiation/cipher change.
- Record defragmentation not supported, seems rare over TCP.
- TLS 1.3
- SSL v2 but v2 compat header is supported.
- Some key exchange messages not decoded yet

Decryption code is heavly based on golang crypto/tls and zmap/zcrypto.

Will be base for decoding http2 and other TLS based on protocols.

Fixes #587
2023-03-05 13:52:12 +01:00

97 lines
2.0 KiB
Go

package tlsdecrypt
// TODO: SSLv3 MAC
// TODO: TLS 1.3
import (
"fmt"
"hash"
)
type Decryptor struct {
IsClient bool
Version int
CipherSuite int
MasterSecret []byte
ClientRandom []byte
ServerRandom []byte
halfConn *halfConn
}
type keys struct {
clientCipher any
serverCipher any
clientHash hash.Hash
serverHash hash.Hash
}
// TODO: only need one direction at a time
func establishKeys(
vers uint16,
suite *cipherSuite,
masterSecret []byte,
clientRandom []byte,
serverRandom []byte,
) keys {
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
keysFromMasterSecret(vers, suite, masterSecret, clientRandom, serverRandom, suite.macLen, suite.keyLen, suite.ivLen)
var clientCipher, serverCipher any
var clientHash, serverHash hash.Hash
if suite.aead == nil {
clientCipher = suite.cipher(clientKey, clientIV, true /* for reading */)
clientHash = suite.mac(clientMAC)
serverCipher = suite.cipher(serverKey, serverIV, true /* for reading */)
serverHash = suite.mac(serverMAC)
} else {
clientCipher = suite.aead(clientKey, clientIV)
serverCipher = suite.aead(serverKey, serverIV)
}
return keys{
clientCipher: clientCipher,
serverCipher: serverCipher,
clientHash: clientHash,
serverHash: serverHash,
}
}
func (d *Decryptor) Decrypt(record []byte) ([]byte, error) {
if d.halfConn == nil {
cipherSuite := cipherSuiteByID(uint16(d.CipherSuite))
if cipherSuite == nil {
return nil, fmt.Errorf("unsupported cipher suit %x", d.CipherSuite)
}
keys := establishKeys(
uint16(d.Version),
cipherSuite,
d.MasterSecret,
d.ClientRandom,
d.ServerRandom,
)
var cipher any
var mac hash.Hash
if d.IsClient {
cipher = keys.clientCipher
mac = keys.clientHash
} else {
cipher = keys.serverCipher
mac = keys.serverHash
}
d.halfConn = &halfConn{
version: uint16(d.Version),
cipher: cipher,
mac: mac,
seq: [8]byte{}, // zero
}
}
plain, _, err := d.halfConn.decrypt(record)
return plain, err
}