github.com/eagleql/xray-core@v1.4.4/common/crypto/auth.go (about) 1 package crypto 2 3 import ( 4 "crypto/cipher" 5 "io" 6 "math/rand" 7 8 "github.com/eagleql/xray-core/common" 9 "github.com/eagleql/xray-core/common/buf" 10 "github.com/eagleql/xray-core/common/bytespool" 11 "github.com/eagleql/xray-core/common/protocol" 12 ) 13 14 type BytesGenerator func() []byte 15 16 func GenerateEmptyBytes() BytesGenerator { 17 var b [1]byte 18 return func() []byte { 19 return b[:0] 20 } 21 } 22 23 func GenerateStaticBytes(content []byte) BytesGenerator { 24 return func() []byte { 25 return content 26 } 27 } 28 29 func GenerateIncreasingNonce(nonce []byte) BytesGenerator { 30 c := append([]byte(nil), nonce...) 31 return func() []byte { 32 for i := range c { 33 c[i]++ 34 if c[i] != 0 { 35 break 36 } 37 } 38 return c 39 } 40 } 41 42 func GenerateInitialAEADNonce() BytesGenerator { 43 return GenerateIncreasingNonce([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 44 } 45 46 type Authenticator interface { 47 NonceSize() int 48 Overhead() int 49 Open(dst, cipherText []byte) ([]byte, error) 50 Seal(dst, plainText []byte) ([]byte, error) 51 } 52 53 type AEADAuthenticator struct { 54 cipher.AEAD 55 NonceGenerator BytesGenerator 56 AdditionalDataGenerator BytesGenerator 57 } 58 59 func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) { 60 iv := v.NonceGenerator() 61 if len(iv) != v.AEAD.NonceSize() { 62 return nil, newError("invalid AEAD nonce size: ", len(iv)) 63 } 64 65 var additionalData []byte 66 if v.AdditionalDataGenerator != nil { 67 additionalData = v.AdditionalDataGenerator() 68 } 69 return v.AEAD.Open(dst, iv, cipherText, additionalData) 70 } 71 72 func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) { 73 iv := v.NonceGenerator() 74 if len(iv) != v.AEAD.NonceSize() { 75 return nil, newError("invalid AEAD nonce size: ", len(iv)) 76 } 77 78 var additionalData []byte 79 if v.AdditionalDataGenerator != nil { 80 additionalData = v.AdditionalDataGenerator() 81 } 82 return v.AEAD.Seal(dst, iv, plainText, additionalData), nil 83 } 84 85 type AuthenticationReader struct { 86 auth Authenticator 87 reader *buf.BufferedReader 88 sizeParser ChunkSizeDecoder 89 sizeBytes []byte 90 transferType protocol.TransferType 91 padding PaddingLengthGenerator 92 size uint16 93 paddingLen uint16 94 hasSize bool 95 done bool 96 } 97 98 func NewAuthenticationReader(auth Authenticator, sizeParser ChunkSizeDecoder, reader io.Reader, transferType protocol.TransferType, paddingLen PaddingLengthGenerator) *AuthenticationReader { 99 r := &AuthenticationReader{ 100 auth: auth, 101 sizeParser: sizeParser, 102 transferType: transferType, 103 padding: paddingLen, 104 sizeBytes: make([]byte, sizeParser.SizeBytes()), 105 } 106 if breader, ok := reader.(*buf.BufferedReader); ok { 107 r.reader = breader 108 } else { 109 r.reader = &buf.BufferedReader{Reader: buf.NewReader(reader)} 110 } 111 return r 112 } 113 114 func (r *AuthenticationReader) readSize() (uint16, uint16, error) { 115 if r.hasSize { 116 r.hasSize = false 117 return r.size, r.paddingLen, nil 118 } 119 if _, err := io.ReadFull(r.reader, r.sizeBytes); err != nil { 120 return 0, 0, err 121 } 122 var padding uint16 123 if r.padding != nil { 124 padding = r.padding.NextPaddingLen() 125 } 126 size, err := r.sizeParser.Decode(r.sizeBytes) 127 return size, padding, err 128 } 129 130 var errSoft = newError("waiting for more data") 131 132 func (r *AuthenticationReader) readBuffer(size int32, padding int32) (*buf.Buffer, error) { 133 b := buf.New() 134 if _, err := b.ReadFullFrom(r.reader, size); err != nil { 135 b.Release() 136 return nil, err 137 } 138 size -= padding 139 rb, err := r.auth.Open(b.BytesTo(0), b.BytesTo(size)) 140 if err != nil { 141 b.Release() 142 return nil, err 143 } 144 b.Resize(0, int32(len(rb))) 145 return b, nil 146 } 147 148 func (r *AuthenticationReader) readInternal(soft bool, mb *buf.MultiBuffer) error { 149 if soft && r.reader.BufferedBytes() < r.sizeParser.SizeBytes() { 150 return errSoft 151 } 152 153 if r.done { 154 return io.EOF 155 } 156 157 size, padding, err := r.readSize() 158 if err != nil { 159 return err 160 } 161 162 if size == uint16(r.auth.Overhead())+padding { 163 r.done = true 164 return io.EOF 165 } 166 167 if soft && int32(size) > r.reader.BufferedBytes() { 168 r.size = size 169 r.paddingLen = padding 170 r.hasSize = true 171 return errSoft 172 } 173 174 if size <= buf.Size { 175 b, err := r.readBuffer(int32(size), int32(padding)) 176 if err != nil { 177 return nil 178 } 179 *mb = append(*mb, b) 180 return nil 181 } 182 183 payload := bytespool.Alloc(int32(size)) 184 defer bytespool.Free(payload) 185 186 if _, err := io.ReadFull(r.reader, payload[:size]); err != nil { 187 return err 188 } 189 190 size -= padding 191 192 rb, err := r.auth.Open(payload[:0], payload[:size]) 193 if err != nil { 194 return err 195 } 196 197 *mb = buf.MergeBytes(*mb, rb) 198 return nil 199 } 200 201 func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) { 202 const readSize = 16 203 mb := make(buf.MultiBuffer, 0, readSize) 204 if err := r.readInternal(false, &mb); err != nil { 205 buf.ReleaseMulti(mb) 206 return nil, err 207 } 208 209 for i := 1; i < readSize; i++ { 210 err := r.readInternal(true, &mb) 211 if err == errSoft || err == io.EOF { 212 break 213 } 214 if err != nil { 215 buf.ReleaseMulti(mb) 216 return nil, err 217 } 218 } 219 220 return mb, nil 221 } 222 223 type AuthenticationWriter struct { 224 auth Authenticator 225 writer buf.Writer 226 sizeParser ChunkSizeEncoder 227 transferType protocol.TransferType 228 padding PaddingLengthGenerator 229 } 230 231 func NewAuthenticationWriter(auth Authenticator, sizeParser ChunkSizeEncoder, writer io.Writer, transferType protocol.TransferType, padding PaddingLengthGenerator) *AuthenticationWriter { 232 w := &AuthenticationWriter{ 233 auth: auth, 234 writer: buf.NewWriter(writer), 235 sizeParser: sizeParser, 236 transferType: transferType, 237 } 238 if padding != nil { 239 w.padding = padding 240 } 241 return w 242 } 243 244 func (w *AuthenticationWriter) seal(b []byte) (*buf.Buffer, error) { 245 encryptedSize := int32(len(b) + w.auth.Overhead()) 246 var paddingSize int32 247 if w.padding != nil { 248 paddingSize = int32(w.padding.NextPaddingLen()) 249 } 250 251 sizeBytes := w.sizeParser.SizeBytes() 252 totalSize := sizeBytes + encryptedSize + paddingSize 253 if totalSize > buf.Size { 254 return nil, newError("size too large: ", totalSize) 255 } 256 257 eb := buf.New() 258 w.sizeParser.Encode(uint16(encryptedSize+paddingSize), eb.Extend(sizeBytes)) 259 if _, err := w.auth.Seal(eb.Extend(encryptedSize)[:0], b); err != nil { 260 eb.Release() 261 return nil, err 262 } 263 if paddingSize > 0 { 264 // With size of the chunk and padding length encrypted, the content of padding doesn't matter much. 265 paddingBytes := eb.Extend(paddingSize) 266 common.Must2(rand.Read(paddingBytes)) 267 } 268 269 return eb, nil 270 } 271 272 func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error { 273 defer buf.ReleaseMulti(mb) 274 275 var maxPadding int32 276 if w.padding != nil { 277 maxPadding = int32(w.padding.MaxPaddingLen()) 278 } 279 280 payloadSize := buf.Size - int32(w.auth.Overhead()) - w.sizeParser.SizeBytes() - maxPadding 281 mb2Write := make(buf.MultiBuffer, 0, len(mb)+10) 282 283 temp := buf.New() 284 defer temp.Release() 285 286 rawBytes := temp.Extend(payloadSize) 287 288 for { 289 nb, nBytes := buf.SplitBytes(mb, rawBytes) 290 mb = nb 291 292 eb, err := w.seal(rawBytes[:nBytes]) 293 294 if err != nil { 295 buf.ReleaseMulti(mb2Write) 296 return err 297 } 298 mb2Write = append(mb2Write, eb) 299 if mb.IsEmpty() { 300 break 301 } 302 } 303 304 return w.writer.WriteMultiBuffer(mb2Write) 305 } 306 307 func (w *AuthenticationWriter) writePacket(mb buf.MultiBuffer) error { 308 defer buf.ReleaseMulti(mb) 309 310 mb2Write := make(buf.MultiBuffer, 0, len(mb)+1) 311 312 for _, b := range mb { 313 if b.IsEmpty() { 314 continue 315 } 316 317 eb, err := w.seal(b.Bytes()) 318 if err != nil { 319 continue 320 } 321 322 mb2Write = append(mb2Write, eb) 323 } 324 325 if mb2Write.IsEmpty() { 326 return nil 327 } 328 329 return w.writer.WriteMultiBuffer(mb2Write) 330 } 331 332 // WriteMultiBuffer implements buf.Writer. 333 func (w *AuthenticationWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { 334 if mb.IsEmpty() { 335 eb, err := w.seal([]byte{}) 336 common.Must(err) 337 return w.writer.WriteMultiBuffer(buf.MultiBuffer{eb}) 338 } 339 340 if w.transferType == protocol.TransferTypeStream { 341 return w.writeStream(mb) 342 } 343 344 return w.writePacket(mb) 345 }