-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpacket.go
302 lines (248 loc) · 11.6 KB
/
packet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
package quic
import (
"bytes"
"fmt"
)
func createLongHeader(qinfo QPacketInfo, ptype int) (longHeader LongHeader, packetNum []byte) {
// パケット番号長が2byteの場合0xC1になる
// 先頭の6bitは110000, 下位の2bitがLenghtを表す
// 1 LongHeader
// 1 Fixed bit
// 00 Packet Type
// 00 Reserved
// 17.2. Long Header Packets
// That is, the length of the Packet Number field is the value of this field plus one.
// 生成するときは1をパケット番号長から引く、2-1は1、2bitの2進数で表すと01
// 11000001 = 0xC1 となる(Initial Packet)
// 11100001 = 0xE1 となる(Handshake Packet)
var firstByte byte
switch ptype {
case LongHeaderPacketTypeInitial:
// とりあえず2byte
if qinfo.ClientPacketNumberLength == 2 {
packetNum = UintTo2byte(uint16(qinfo.InitialPacketNumber))
} else if qinfo.ClientPacketNumberLength == 4 {
packetNum = UintTo4byte(uint32(qinfo.InitialPacketNumber))
}
if len(packetNum) == 2 {
firstByte = 0xC1
} else if len(packetNum) == 4 {
firstByte = 0xC3
}
case LongHeaderPacketTypeHandshake:
if qinfo.ClientPacketNumberLength == 2 {
packetNum = UintTo2byte(uint16(qinfo.HandshakePacketNumber))
} else if qinfo.ClientPacketNumberLength == 4 {
packetNum = UintTo4byte(uint32(qinfo.HandshakePacketNumber))
}
if len(packetNum) == 2 {
firstByte = 0xE1
} else if len(packetNum) == 4 {
firstByte = 0xE3
}
}
longHeader.HeaderByte = []byte{firstByte}
longHeader.Version = []byte{0x00, 0x00, 0x00, 0x01}
// destination connection idをセット
if qinfo.DestinationConnID == nil {
longHeader.DestConnIDLength = []byte{0x00}
} else {
longHeader.DestConnIDLength = []byte{byte(len(qinfo.DestinationConnID))}
longHeader.DestConnID = qinfo.DestinationConnID
}
// source connection id をセット
if qinfo.SourceConnID == nil {
longHeader.SourceConnIDLength = []byte{0x00}
} else {
longHeader.SourceConnIDLength = []byte{byte(len(qinfo.SourceConnID))}
longHeader.SourceConnID = qinfo.SourceConnID
}
return longHeader, packetNum
}
// Inital Packetのヘッダを生成する
func NewInitialPacketHeader(qinfo QPacketInfo) (initPacket InitialPacket) {
initPacket.LongHeader, initPacket.PacketNumber = createLongHeader(qinfo, LongHeaderPacketTypeInitial)
// トークンをセット
// トークンがnilならLengthに0だけをセットする
// トークンがあれば可変長整数でトークンの長さをLengthにセットしてトークンをセットする
if qinfo.Token == nil {
initPacket.TokenLength = []byte{0x00}
} else {
initPacket.TokenLength = EncodeVariableInt(len(qinfo.Token))
initPacket.Token = qinfo.Token
}
// Lengthを空でセット
initPacket.Length = []byte{0x00, 0x00}
return initPacket
}
// Handshake Packetのヘッダを生成する
func NewHandshakePacket(qinfo QPacketInfo) (handshake HandshakePacket) {
handshake.LongHeader, handshake.PacketNumber = createLongHeader(qinfo, LongHeaderPacketTypeHandshake)
return handshake
}
func (*InitialPacket) ToHeaderByte(initPacket InitialPacket) (headerByte []byte) {
headerByte = toByteArr(initPacket.LongHeader)
// set token
if bytes.Equal(initPacket.TokenLength, []byte{0x00}) {
headerByte = append(headerByte, initPacket.TokenLength...)
} else {
headerByte = append(headerByte, initPacket.TokenLength...)
headerByte = append(headerByte, initPacket.Token...)
}
// パケットのLengthを可変長整数でエンコードして返す
//if encodeLen {
// fmt.Printf("Init pakcet length is %x\n", initPacket.Length)
// headerByte = append(headerByte, EncodeVariableInt(int(sumByteArr(initPacket.Length)))...)
//} else {
headerByte = append(headerByte, initPacket.Length...)
headerByte = append(headerByte, initPacket.PacketNumber...)
return headerByte
}
func (*HandshakePacket) ToHeaderByte(handshake HandshakePacket) (packet []byte) {
packet = toByteArr(handshake.LongHeader)
//if encodeLen {
// packet = append(packet, EncodeVariableInt(int(sumByteArr(handshake.Length)))...)
//} else {
packet = append(packet, handshake.Length...)
packet = append(packet, handshake.PacketNumber...)
return packet
}
func (*ShortHeader) ToHeaderByte(short ShortHeader) (header []byte) {
header = append(header, short.HeaderByte...)
header = append(header, short.DestConnID...)
header = append(header, short.PacketNumber...)
return header
}
// Initial Packetを生成してTLSの鍵情報と返す
func (*InitialPacket) CreateInitialPacket(tlsinfo TLSInfo) (TLSInfo, []byte) {
var chello []byte
var initPacket InitialPacket
// Destination Connection IDからInitial Packetの暗号化に使う鍵を生成する
keyblock := CreateQuicInitialSecret(tlsinfo.QPacketInfo.DestinationConnID)
tlsinfo.ECDHEKeys, chello = NewQuicClientHello()
cryptoByte := toByteArr(NewCryptoFrame(chello, true))
// Packet Numberが0の時、初回だけ、Client Helloのパケットを保存
if tlsinfo.QPacketInfo.InitialPacketNumber == 0 {
tlsinfo.HandshakeMessages = chello
}
// set quic keyblock
tlsinfo.QuicKeyBlock = keyblock
initPacket = NewInitialPacketHeader(tlsinfo.QPacketInfo)
// Padding Frame の長さ = 1252 - LongHeaderのLength - Crypto FrameのLength - 16(AEAD暗号化したときのOverhead)
paddingLength := 1252 - len(initPacket.ToHeaderByte(initPacket)) - len(cryptoByte) - 16
initPacket.Payload = UnshiftPaddingFrame(cryptoByte, paddingLength)
// PayloadのLength + Packet番号のLength + AEADの認証タグ長=16
length := len(initPacket.Payload) + len(initPacket.PacketNumber) + 16
// 可変長整数のエンコードをしてLengthをセット
initPacket.Length = EncodeVariableInt(length)
// ヘッダをByteにする
headerByte := initPacket.ToHeaderByte(initPacket)
// PaddingとCrypto FrameのPayloadを暗号化する
encpayload := EncryptClientPayload(initPacket.PacketNumber, headerByte, initPacket.Payload, keyblock)
// 暗号化したPayloadをヘッダとくっつける
packet := headerByte
packet = append(packet, encpayload...)
// ヘッダ内のPacket Number Lengthの2bitとPacket Numberを暗号化する
protectPacket := ProtectHeader(len(headerByte)-2, packet, keyblock.ClientHeaderProtection, true)
return tlsinfo, protectPacket
}
// サーバからのTLS Handshakeに送り返すACKパケットを作成
func (*InitialPacket) CreateInitialAckPacket(tlsinfo TLSInfo) []byte {
//tlsinfo.QPacketInfo.DestinationConnID = strtoByte("4a4b30eb")
initPacket := NewInitialPacketHeader(tlsinfo.QPacketInfo)
// ACK Frameを作成
ack := toByteArr(NewAckFrame(tlsinfo.QPacketInfo.AckCount))
// Padding Frame の長さ = 1252 - LongHeaderのLength - Crypto FrameのLength - 16
paddingLength := 1252 - len(initPacket.ToHeaderByte(initPacket)) - len(ack) - 16
// PaddingしてPacket Sizeを増やす
initPacket.Payload = AppendPaddingFrame(ack, paddingLength)
// PayloadのLength + Packet番号のLength + AEADの認証タグ長=16
length := len(initPacket.Payload) + len(initPacket.PacketNumber) + 16
// 可変長整数のエンコードをしてLengthをセット
initPacket.Length = EncodeVariableInt(length)
// ヘッダをByteにする
headerByte := initPacket.ToHeaderByte(initPacket)
// PaddingとACK FrameのPayloadを暗号化する
encpayload := EncryptClientPayload(initPacket.PacketNumber, headerByte, initPacket.Payload, tlsinfo.QuicKeyBlock)
// 暗号化したPayloadをヘッダとくっつける
packet := headerByte
packet = append(packet, encpayload...)
// ヘッダ内のPacket Number Lengthの2bitとPacket Numberを暗号化する
return ProtectHeader(len(headerByte)-2, packet, tlsinfo.QuicKeyBlock.ClientHeaderProtection, true)
}
// TLSのClient Finishedメッセージを送るHandshakeパケットを作成
func (*HandshakePacket) CreateHandshakePacket(tlsinfo TLSInfo) []byte {
handshake := NewHandshakePacket(tlsinfo.QPacketInfo)
// 1に増やす
tlsinfo.QPacketInfo.AckCount++
ack := NewAckFrame(tlsinfo.QPacketInfo.AckCount)
crypto := CreateClientFinished(tlsinfo.HandshakeMessages, tlsinfo.KeyBlockTLS13.ClientFinishedKey)
payload := toByteArr(ack)
payload = append(payload, toByteArr(crypto)...)
// PayloadのLength + Packet番号のLength + AEADの認証タグ長=16
length := len(payload) + len(handshake.PacketNumber) + 16
// 可変長整数のエンコードをしてLengthをセット
handshake.Length = EncodeVariableInt(length)
// ヘッダをByteにする
headerByte := handshake.ToHeaderByte(handshake)
clientkey := QuicKeyBlock{
ClientKey: tlsinfo.KeyBlockTLS13.ClientHandshakeKey,
ClientIV: tlsinfo.KeyBlockTLS13.ClientHandshakeIV,
}
// PaddingとACK FrameのPayloadを暗号化する
encpayload := EncryptClientPayload(handshake.PacketNumber, headerByte, payload, clientkey)
// 暗号化したPayloadをヘッダとくっつける
packet := headerByte
packet = append(packet, encpayload...)
// ヘッダ内のPacket Number Lengthの2bitとPacket Numberを暗号化する
return ProtectHeader(len(headerByte)-2, packet, tlsinfo.KeyBlockTLS13.ClientHandshakeHPKey, true)
}
// Inital packetを復号する。復号して結果をパースしてQuicパケットのframeにして返す。
func (*InitialPacket) ToPlainQuicPacket(initPacket InitialPacket, tlsinfo TLSInfo) []interface{} {
// Initial Packetのペイロードを復号
plain := DecryptQuicPayload(initPacket.PacketNumber, initPacket.ToHeaderByte(initPacket), initPacket.Payload, tlsinfo.QuicKeyBlock)
// 復号した結果をパースしてQuicパケットのFrameにして返す
return ParseQuicFrame(plain, tlsinfo.QPacketInfo.CryptoFrameOffset)
}
// Handshake packetを復号する。復号して結果をパースしてQuicパケットのframeにして返す。
func (*HandshakePacket) ToPlainQuicPacket(handshake HandshakePacket, tlsinfo TLSInfo) (frames []interface{}) {
serverkey := QuicKeyBlock{
ServerKey: tlsinfo.KeyBlockTLS13.ServerHandshakeKey,
ServerIV: tlsinfo.KeyBlockTLS13.ServerHandshakeIV,
}
// Handshake packetのpayloadを復号
plain := DecryptQuicPayload(handshake.PacketNumber, handshake.ToHeaderByte(handshake), handshake.Payload, serverkey)
// 復号した結果をパースしてQuicパケットのFrameにして返す
return ParseQuicFrame(plain, tlsinfo.QPacketInfo.CryptoFrameOffset)
}
func (*ShortHeader) ToPlainQuicPacket(short ShortHeader, tlsinfo TLSInfo) (frames []interface{}) {
serverkey := QuicKeyBlock{
ServerKey: tlsinfo.KeyBlockTLS13.ServerAppKey,
ServerIV: tlsinfo.KeyBlockTLS13.ServerAppIV,
}
plain := DecryptQuicPayload(short.PacketNumber, short.ToHeaderByte(short), short.Payload, serverkey)
fmt.Printf("Decrypt plain message is %x\n", plain)
// 復号した結果をパースしてQuicパケットのFrameにして返す
return ParseQuicFrame(plain, 0)
}
func (*ShortHeader) CreateShortHeaderPacket(tlsinfo TLSInfo, payload []byte) []byte {
// Packet Number Lengthは2byteだから01000001
headerByte := []byte{0x41}
headerByte = append(headerByte, tlsinfo.QPacketInfo.DestinationConnID...)
pnumOffset := len(headerByte)
packetnum := UintTo2byte(uint16(tlsinfo.QPacketInfo.ShortHeaderPacketNumber))
headerByte = append(headerByte, packetnum...)
clientkey := QuicKeyBlock{
ClientKey: tlsinfo.KeyBlockTLS13.ClientAppKey,
ClientIV: tlsinfo.KeyBlockTLS13.ClientAppIV,
}
// PaddingとACK FrameのPayloadを暗号化する
encpayload := EncryptClientPayload(packetnum, headerByte, payload, clientkey)
fmt.Printf("enc payload is %x\n", encpayload)
fmt.Printf("headerByte is %x\n", headerByte)
// 暗号化したPayloadをヘッダとくっつける
packet := headerByte
packet = append(packet, encpayload...)
// ヘッダ内のPacket Number Lengthの2bitとPacket Numberを暗号化する
return ProtectHeader(pnumOffset, packet, tlsinfo.KeyBlockTLS13.ClientAppHPKey, false)
}