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