Skip to content

Commit

Permalink
Merge pull request #45 from ddddddO/refactor_tls_12
Browse files Browse the repository at this point in the history
少しrefactor
  • Loading branch information
ddddddO authored Jul 27, 2024
2 parents ca4fa5c + cb167d1 commit 5cdbb58
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 51 deletions.
27 changes: 7 additions & 20 deletions internal/debugging/networkinterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func (dnw *debugNetworkInterface) SendTCP3wayhandshake(firsthopMACAddr [6]byte)
}

func (dnw *debugNetworkInterface) SendTCP3wayAndTLShandshake(firsthopMACAddr [6]byte) error {
var srcPort uint16 = 0xa265
var srcPort uint16 = 0xa288
var dstPort uint16 = 0x28cb // 10443
var srcIPAddr uint32 = 0xac184fcf // 172.23.242.78
var dstIPAddr uint32 = 0xc0a80a6e // raspberry pi
Expand Down Expand Up @@ -382,14 +382,11 @@ func (dnw *debugNetworkInterface) SendTCP3wayAndTLShandshake(firsthopMACAddr [6]
return err
}

// TODO: ここでTLS Client Helloを送る
// ここで TLS Client Helloを送る
if err := dnw.SendTLSClientHello(tlsClientHello, srcPort, dstPort, srcIPAddr, dstIPAddr, firsthopMACAddr, tcp.Sequence, tcp.Acknowledgment); err != nil {
return err
}

// if err := dnw.SendHTTPget(srcPort, dstPort, srcIPAddr, dstIPAddr, firsthopMACAddr, tcp.Sequence, tcp.Acknowledgment); err != nil {
// return err
// }
continue
}

Expand All @@ -404,21 +401,12 @@ func (dnw *debugNetworkInterface) SendTCP3wayAndTLShandshake(firsthopMACAddr [6]

// ServerHelloを受信
// TODO: (10)443ポートがdstで絞った方がいいかも
// SeverHello(0x02) / Handshake(0x16)
if bytes.Equal(tlsHandshakeType, []byte{0x02}) && bytes.Equal(tlsContentType, []byte{0x16}) {
// SeverHello(0x02)
if bytes.Equal(tlsHandshakeType, []byte{0x02}) && bytes.Equal(tlsContentType, []byte{p.TLS_CONTENT_TYPE_HANDSHAKE}) {
log.Printf("tlsHandshakeType: %x\n", tlsHandshakeType)

log.Println("passive TLS ServerHello")
tlsServerHello = p.ParsedTLSServerHello(tcp.Data)

// log.Printf("\tServerHello.RecordLayer.ContentType: %x\n", tlsServerHello.ServerHello.RecordLayer.ContentType)
// log.Printf("\tServerHello.HandshakeProtocol.Version: %x\n", tlsServerHello.ServerHello.HandshakeProtocol.Version)
// log.Printf("\tServerHello.HandshakeProtocol.CipherSuites: %x\n", tlsServerHello.ServerHello.HandshakeProtocol.CipherSuites)
// log.Printf("\tServerHello.HandshakeProtocol.Random:\n%x\n", tlsServerHello.ServerHello.HandshakeProtocol.Random)
// log.Printf("\tServerHelloDone.RecordLayer.ContentType: %x\n", tlsServerHello.ServerHelloDone.RecordLayer.ContentType)
// log.Printf("\tServerHelloDone.HandshakeProtocol.HandshakeType: %x\n", tlsServerHello.ServerHelloDone.HandshakeProtocol.HandshakeType)
// log.Printf("\tServerHelloDone.HandshakeProtocol.Length: %x\n", tlsServerHello.ServerHelloDone.HandshakeProtocol.Length)

if err := tlsServerHello.Certificate.Validate(); err != nil {
return err
}
Expand All @@ -437,8 +425,8 @@ func (dnw *debugNetworkInterface) SendTCP3wayAndTLShandshake(firsthopMACAddr [6]
return err
}

// TODO: さらにClientKeyExchangeなどを返す
tlsClientKeyExchange, keyblock, clientSequence, master, tlsClientFinished = p.NewTLSClientKeyExchange(
// さらに ClientKeyExchange や Finished などを返す
tlsClientKeyExchange, keyblock, clientSequence, master, tlsClientFinished = p.NewTLSClientKeyExchangeAndChangeCipherSpecAndFinished(
tlsClientHello,
tlsServerHello,
)
Expand All @@ -460,8 +448,7 @@ func (dnw *debugNetworkInterface) SendTCP3wayAndTLShandshake(firsthopMACAddr [6]

// ChangeCipherSpec/Finishedを受信
// TODO: (10)443ポートがdstとかもっと絞った方がいいかも
// Handshake(0x14)
if bytes.Equal(tlsContentType, []byte{0x14}) {
if bytes.Equal(tlsContentType, []byte{p.TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC}) {
log.Println("recieved ChangeCipherSpec/Finished !!")

verifingData := &p.ForVerifing{
Expand Down
70 changes: 39 additions & 31 deletions tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (
"log"
)

const TLS_CONTENT_TYPE_HANDSHAKE = 0x16
const TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 0x14
const TLS_CONTENT_TYPE_APPLICATION_DATA = 0x17

// ref: https://tls12.xargs.org/#client-hello/annotated
// 以降のstructのフィールドはWiresharkを見つつ補完
type TLSRecordLayer struct {
Expand Down Expand Up @@ -93,11 +97,10 @@ var TLS_VERSION_1_2 = []byte{0x03, 0x03}
func NewTLSClientHello() *TLSClientHello {
handshake := &TLSHandshakeProtocol{
HandshakeType: []byte{CLIENT_HELLO},
Length: []byte{0x00, 0x00, 0x2b}, // 2b = 43byte
// Length: []byte{0x00, 0x00, 0x4a}, // 4a = 74byte
Version: TLS_VERSION_1_2,
Random: make([]byte, 32), // 000000....
SessionID: []byte{0x00},
Length: []byte{0x00, 0x00, 0x00}, // 後で計算して求めるが、初期化のため
Version: TLS_VERSION_1_2,
Random: make([]byte, 32), // 000000....
SessionID: []byte{0x00},
// SessionID: make([]byte, 32),
CipherSuites: []uint16{
// tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
Expand All @@ -119,21 +122,29 @@ func NewTLSClientHello() *TLSClientHello {
// tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
// tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
},
CompressionMethodsLength: []byte{0x01},
CompressionMethodsLength: []byte{0x00}, // 後で計算して求めるが、初期化のため
CompressionMethods: []byte{COMPRESSION_METHOD_NULL},
ExtensionsLength: []byte{0x00, 0x00},
ExtensionsLength: []byte{0x00, 0x00}, // 後で計算して求めるが、初期化のため
Extentions: []byte{},
}

lengthHandshake := &bytes.Buffer{}
handshake.CompressionMethodsLength = []byte{byte(len(handshake.CompressionMethods))}
tmp := &bytes.Buffer{}
WriteUint16(tmp, uint16(len(handshake.Extentions))) // TODO: ここ実際にExtentions指定してないで実装したから、指定したらバグってるかも
handshake.ExtensionsLength = tmp.Bytes()

lengthAll := &bytes.Buffer{}
isFromServer := false
WriteUint16(lengthHandshake, uint16(len(handshake.Bytes(isFromServer))))
WriteUint16(lengthAll, uint16(len(handshake.Bytes(isFromServer))))

// 全体の長さ - 4 でいいはず
handshake.Length = uintTo3byte(uint32(len(handshake.Bytes(isFromServer))) - 4)

return &TLSClientHello{
RecordLayer: &TLSRecordLayer{
ContentType: []byte{0x16},
Version: []byte{0x03, 0x01},
Length: lengthHandshake.Bytes(),
ContentType: []byte{TLS_CONTENT_TYPE_HANDSHAKE},
Version: TLS_VERSION_1_2,
Length: lengthAll.Bytes(),
},
HandshakeProtocol: handshake,
}
Expand Down Expand Up @@ -363,9 +374,8 @@ func (e *EncryptedHandshakeMessage) Bytes() []byte {

const TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 0x10
const TLS_HANDSHAKE_TYPE_FINISHED = 0x14
const TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 0x14

func NewTLSClientKeyExchange(clientHello *TLSClientHello, serverHello *TLSServerHello) (*TLSClientKeyExchange, *KeyBlock, int, []byte, []byte) {
func NewTLSClientKeyExchangeAndChangeCipherSpecAndFinished(clientHello *TLSClientHello, serverHello *TLSServerHello) (*TLSClientKeyExchange, *KeyBlock, int, []byte, []byte) {
publicKey := serverHello.Certificate.ServerPublicKey()
preMastersecret, encryptedPreMastersecret := generatePreMasterSecret(publicKey)

Expand All @@ -382,24 +392,31 @@ func NewTLSClientKeyExchange(clientHello *TLSClientHello, serverHello *TLSServer

clientKeyExchange := &ClientKeyExchange{
RecordLayer: &TLSRecordLayer{
ContentType: []byte{0x16},
ContentType: []byte{TLS_CONTENT_TYPE_HANDSHAKE},
Version: TLS_VERSION_1_2,
Length: []byte{0x01, 0x06}, // 262
Length: []byte{0x00, 0x00}, // 後で計算するが、初期化のため
},
HandshakeProtocol: &TLSHandshakeProtocol{
HandshakeType: []byte{TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE},
Length: uintTo3byte(uint32(len(rsaEncryptedPreMasterSecret.Bytes()))),
},
RSAEncryptedPreMasterSecret: rsaEncryptedPreMasterSecret,
}
// -5でいいみたい
tmp := &bytes.Buffer{}
WriteUint16(tmp, uint16(len(clientKeyExchange.Bytes())-5))
clientKeyExchange.RecordLayer.Length = tmp.Bytes()

changeCipherSpecMessage := []byte{0x01}
tmp = &bytes.Buffer{}
WriteUint16(tmp, uint16(len(changeCipherSpecMessage)))
changeCipherSpecProtocol := &ChangeCipherSpecProtocol{
RecordLayer: &TLSRecordLayer{
ContentType: []byte{TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC},
Version: TLS_VERSION_1_2,
Length: []byte{0x00, 0x01},
Length: tmp.Bytes(),
},
ChangeCipherSpecMessage: []byte{0x01},
ChangeCipherSpecMessage: changeCipherSpecMessage,
}

rawFinished, encrypted, keyblock, clientSequence, master := generateEncryptedHandshakeMessage(preMastersecret, clientHello, serverHello, clientKeyExchange)
Expand All @@ -412,12 +429,6 @@ func NewTLSClientKeyExchange(clientHello *TLSClientHello, serverHello *TLSServer
}, keyblock, clientSequence, master, rawFinished
}

func lengthEncryptedHandshakeMessage_(b []byte) []byte {
buf := make([]byte, 2)
binary.BigEndian.PutUint16(buf, uint16(len(b)))
return buf
}

// ref: https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.7.1
func generatePreMasterSecret(publicKey *rsa.PublicKey) ([]byte, []byte) {
random := make([]byte, 46)
Expand Down Expand Up @@ -481,7 +492,7 @@ func generateEncryptedHandshakeMessage(preMasterSecret []byte, clientHello *TLSC
handshakes = append(handshakes, serverHello.ServerHelloDone.HandshakeProtocol.Bytes(isFromServer)...)
handshakes = append(handshakes, clientKeyExchange.HandshakeProtocol.Bytes(!isFromServer)...)
handshakes = append(handshakes, clientKeyExchange.RSAEncryptedPreMasterSecret.Bytes()...)
// TODO: ChangeCipherSpecは含まれない記載がrfcにある. ref: https://rfcs-web-fc2-com.translate.goog/rfc5246.html?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja#section-7.4 の「7.4.9 . 完了」
// ChangeCipherSpecは含まれない記載がrfcにある. ref: https://rfcs-web-fc2-com.translate.goog/rfc5246.html?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja#section-7.4 の「7.4.9 . 完了」
// handshakes = append(handshakes, changeCipherSpecProtocol.ChangeCipherSpecMessage...)

hasher := sha256.New()
Expand All @@ -504,7 +515,7 @@ func encryptClientMessage(keyblock *KeyBlock, plaintext []byte) ([]byte, int) {
log.Printf("length.Bytes(): %x\n", length.Bytes())

h := &TLSRecordLayer{
ContentType: []byte{0x16},
ContentType: []byte{TLS_CONTENT_TYPE_HANDSHAKE},
Version: TLS_VERSION_1_2,
Length: length.Bytes(),
}
Expand Down Expand Up @@ -606,8 +617,7 @@ func ParsedTLSChangeCipherSpecAndFinished(b []byte, keyblock *KeyBlock, clientSe
RawEncrypted: b[11:51], // TODO: とりあえずベタで指定
}

contentType := 0x16 // TODO: 定数
plaintext := decryptServerMessage(finished, keyblock, clientSequenceNum, contentType)
plaintext := decryptServerMessage(finished, keyblock, clientSequenceNum, TLS_CONTENT_TYPE_HANDSHAKE)
log.Printf("Finishe.decrypted text:\n%x\n", plaintext)
if verifyTLSFinished(plaintext, verifyingData) {
log.Println("Succeeded verify!!")
Expand Down Expand Up @@ -674,7 +684,7 @@ func verifyTLSFinished(target []byte, v *ForVerifing) bool {
handshakes = append(handshakes, v.ServerHello.ServerHelloDone.HandshakeProtocol.Bytes(isFromServer)...)
handshakes = append(handshakes, v.ClientKeyExchange.HandshakeProtocol.Bytes(!isFromServer)...)
handshakes = append(handshakes, v.ClientKeyExchange.RSAEncryptedPreMasterSecret.Bytes()...)
// TODO: ChangeCipherSpecは含まれない記載がrfcにある. ref: https://rfcs-web-fc2-com.translate.goog/rfc5246.html?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja#section-7.4 の「7.4.9 . 完了」
// ChangeCipherSpecは含まれない記載がrfcにある. ref: https://rfcs-web-fc2-com.translate.goog/rfc5246.html?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja#section-7.4 の「7.4.9 . 完了」
// handshakes = append(handshakes, changeCipherSpecProtocol.ChangeCipherSpecMessage...)
handshakes = append(handshakes, v.ClientFinished...)

Expand All @@ -700,8 +710,6 @@ func NewTLSApplicationData(data string, keyblock *KeyBlock, clientSequence int)
return encrypted
}

const TLS_CONTENT_TYPE_APPLICATION_DATA = 0x17

// TODO: encryptClientMessage func と共通化を...
func encryptApplicationData(keyblock *KeyBlock, plaintext []byte, clientSequence int) ([]byte, int) {
length := &bytes.Buffer{}
Expand Down

0 comments on commit 5cdbb58

Please sign in to comment.