@@ -30,19 +30,20 @@ var (
30
30
var ClientCipher byte
31
31
32
32
func init () {
33
- if ! HasAESGCMHardwareSupport {
33
+ if HasAESGCMHardwareSupport {
34
34
ClientCipher = 1
35
35
}
36
36
}
37
37
38
38
type ClientInstance struct {
39
39
sync.RWMutex
40
- eKeyNfs * mlkem.EncapsulationKey768
41
- xor uint32
42
- minutes time.Duration
43
- expire time.Time
44
- baseKey []byte
45
- ticket []byte
40
+ nfsEKey * mlkem.EncapsulationKey768
41
+ nfsEKeyBytes []byte
42
+ xor uint32
43
+ minutes time.Duration
44
+ expire time.Time
45
+ baseKey []byte
46
+ ticket []byte
46
47
}
47
48
48
49
type ClientConn struct {
@@ -58,19 +59,22 @@ type ClientConn struct {
58
59
peerCache []byte
59
60
}
60
61
61
- func (i * ClientInstance ) Init (eKeyNfsData []byte , xor uint32 , minutes time.Duration ) (err error ) {
62
- i .eKeyNfs , err = mlkem .NewEncapsulationKey768 (eKeyNfsData )
63
- i .xor = xor
62
+ func (i * ClientInstance ) Init (nfsEKeyBytes []byte , xor uint32 , minutes time.Duration ) (err error ) {
63
+ i .nfsEKey , err = mlkem .NewEncapsulationKey768 (nfsEKeyBytes )
64
+ if xor > 0 {
65
+ i .nfsEKeyBytes = nfsEKeyBytes
66
+ i .xor = xor
67
+ }
64
68
i .minutes = minutes
65
69
return
66
70
}
67
71
68
72
func (i * ClientInstance ) Handshake (conn net.Conn ) (net.Conn , error ) {
69
- if i .eKeyNfs == nil {
73
+ if i .nfsEKey == nil {
70
74
return nil , errors .New ("uninitialized" )
71
75
}
72
- if i .xor == 1 {
73
- conn = NewXorConn (conn , i .eKeyNfs . Bytes () )
76
+ if i .xor > 0 {
77
+ conn = NewXorConn (conn , i .nfsEKeyBytes )
74
78
}
75
79
c := & ClientConn {Conn : conn }
76
80
@@ -86,18 +90,19 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
86
90
i .RUnlock ()
87
91
}
88
92
89
- nfsKey , encapsulatedNfsKey := i . eKeyNfs . Encapsulate ( )
90
- seed := make ([] byte , 64 )
91
- rand . Read ( seed )
92
- dKeyPfs , _ := mlkem . NewDecapsulationKey768 ( seed )
93
- eKeyPfs := dKeyPfs . EncapsulationKey (). Bytes ()
94
- padding := randBetween (100 , 1000 )
93
+ pfsDKeySeed := make ([] byte , 64 )
94
+ rand . Read ( pfsDKeySeed )
95
+ pfsDKey , _ := mlkem . NewDecapsulationKey768 ( pfsDKeySeed )
96
+ pfsEKeyBytes := pfsDKey . EncapsulationKey (). Bytes ( )
97
+ nfsKey , encapsulatedNfsKey := i . nfsEKey . Encapsulate ()
98
+ paddingLen := randBetween (100 , 1000 )
95
99
96
- clientHello := make ([]byte , 1088 + 1184 + 1 + 5 + padding )
97
- copy (clientHello , encapsulatedNfsKey )
98
- copy (clientHello [1088 :], eKeyPfs )
99
- clientHello [2272 ] = ClientCipher
100
- encodeHeader (clientHello [2273 :], int (padding ))
100
+ clientHello := make ([]byte , 1 + 1184 + 1088 + 5 + paddingLen )
101
+ clientHello [0 ] = ClientCipher
102
+ copy (clientHello [1 :], pfsEKeyBytes )
103
+ copy (clientHello [1185 :], encapsulatedNfsKey )
104
+ encodeHeader (clientHello [2273 :], int (paddingLen ))
105
+ rand .Read (clientHello [2278 :])
101
106
102
107
if _ , err := c .Conn .Write (clientHello ); err != nil {
103
108
return nil , err
@@ -111,16 +116,16 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
111
116
encapsulatedPfsKey := peerServerHello [:1088 ]
112
117
c .ticket = peerServerHello [1088 :]
113
118
114
- pfsKey , err := dKeyPfs .Decapsulate (encapsulatedPfsKey )
119
+ pfsKey , err := pfsDKey .Decapsulate (encapsulatedPfsKey )
115
120
if err != nil {
116
121
return nil , err
117
122
}
118
- c .baseKey = append (nfsKey , pfsKey ... )
123
+ c .baseKey = append (pfsKey , nfsKey ... )
119
124
120
125
authKey := make ([]byte , 32 )
121
- hkdf .New (sha256 .New , c .baseKey , encapsulatedNfsKey , eKeyPfs ).Read (authKey )
122
- nonce := make ([ ]byte , 12 )
123
- VLESS , _ := newAead (ClientCipher , authKey ).Open (nil , nonce , c .ticket , encapsulatedPfsKey )
126
+ hkdf .New (sha256 .New , c .baseKey , encapsulatedPfsKey , encapsulatedNfsKey ).Read (authKey )
127
+ nonce := [ 12 ]byte { ClientCipher }
128
+ VLESS , _ := newAead (ClientCipher , authKey ).Open (nil , nonce [:] , c .ticket , pfsEKeyBytes )
124
129
if ! bytes .Equal (VLESS , []byte ("VLESS" )) { // TODO: more message
125
130
return nil , errors .New ("invalid server" )
126
131
}
@@ -140,33 +145,40 @@ func (c *ClientConn) Write(b []byte) (int, error) {
140
145
if len (b ) == 0 {
141
146
return 0 , nil
142
147
}
143
- var data []byte
144
- if c .aead == nil {
145
- c .random = make ([]byte , 32 )
146
- rand .Read (c .random )
147
- key := make ([]byte , 32 )
148
- hkdf .New (sha256 .New , c .baseKey , c .random , c .ticket ).Read (key )
149
- c .aead = newAead (ClientCipher , key )
150
- c .nonce = make ([]byte , 12 )
151
-
152
- data = make ([]byte , 21 + 32 + 5 + len (b )+ 16 )
153
- copy (data , c .ticket )
154
- copy (data [21 :], c .random )
155
- encodeHeader (data [53 :], len (b )+ 16 )
156
- c .aead .Seal (data [:58 ], c .nonce , b , data [53 :58 ])
157
- } else {
158
- data = make ([]byte , 5 + len (b )+ 16 )
159
- encodeHeader (data , len (b )+ 16 )
160
- c .aead .Seal (data [:5 ], c .nonce , b , data [:5 ])
161
- }
162
- increaseNonce (c .nonce )
163
- if _ , err := c .Conn .Write (data ); err != nil {
164
- return 0 , err
148
+ for n := 0 ; n < len (b ); {
149
+ b := b [n :]
150
+ if len (b ) > 8192 {
151
+ b = b [:8192 ] // for avoiding another copy() in server's Read()
152
+ }
153
+ n += len (b )
154
+ var data []byte
155
+ if c .aead == nil {
156
+ c .random = make ([]byte , 32 )
157
+ rand .Read (c .random )
158
+ key := make ([]byte , 32 )
159
+ hkdf .New (sha256 .New , c .baseKey , c .random , c .ticket ).Read (key )
160
+ c .aead = newAead (ClientCipher , key )
161
+ c .nonce = make ([]byte , 12 )
162
+
163
+ data = make ([]byte , 21 + 32 + 5 + len (b )+ 16 )
164
+ copy (data , c .ticket )
165
+ copy (data [21 :], c .random )
166
+ encodeHeader (data [53 :], len (b )+ 16 )
167
+ c .aead .Seal (data [:58 ], c .nonce , b , data [53 :58 ])
168
+ } else {
169
+ data = make ([]byte , 5 + len (b )+ 16 )
170
+ encodeHeader (data , len (b )+ 16 )
171
+ c .aead .Seal (data [:5 ], c .nonce , b , data [:5 ])
172
+ }
173
+ increaseNonce (c .nonce )
174
+ if _ , err := c .Conn .Write (data ); err != nil {
175
+ return 0 , err
176
+ }
165
177
}
166
178
return len (b ), nil
167
179
}
168
180
169
- func (c * ClientConn ) Read (b []byte ) (int , error ) { // after first Write()
181
+ func (c * ClientConn ) Read (b []byte ) (int , error ) {
170
182
if len (b ) == 0 {
171
183
return 0 , nil
172
184
}
@@ -177,11 +189,11 @@ func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
177
189
if _ , err := io .ReadFull (c .Conn , peerHeader ); err != nil {
178
190
return 0 , err
179
191
}
180
- peerPadding , _ := decodeHeader (peerHeader )
181
- if peerPadding == 0 {
192
+ peerPaddingLen , _ := decodeHeader (peerHeader )
193
+ if peerPaddingLen == 0 {
182
194
break
183
195
}
184
- if _ , err := io .ReadFull (c .Conn , make ([]byte , peerPadding )); err != nil {
196
+ if _ , err := io .ReadFull (c .Conn , make ([]byte , peerPaddingLen )); err != nil {
185
197
return 0 , err
186
198
}
187
199
}
@@ -196,7 +208,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
196
208
return 0 , err
197
209
}
198
210
if c .random == nil {
199
- return 0 , errors .New ("can not Read() first " )
211
+ return 0 , errors .New ("empty c.random " )
200
212
}
201
213
peerKey := make ([]byte , 32 )
202
214
hkdf .New (sha256 .New , c .baseKey , peerRandom , c .random ).Read (peerKey )
@@ -228,7 +240,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
228
240
}
229
241
dst := peerData [:peerLength - 16 ]
230
242
if len (dst ) <= len (b ) {
231
- dst = b [:len (dst )] // max=8192 is recommended for peer
243
+ dst = b [:len (dst )] // avoids another copy()
232
244
}
233
245
_ , err = c .peerAead .Open (dst [:0 ], c .peerNonce , peerData , peerHeader )
234
246
increaseNonce (c .peerNonce )
0 commit comments