github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/common/crypto/auth.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"io"
     6  	"math/rand"
     7  
     8  	"v2ray.com/core/common"
     9  	"v2ray.com/core/common/buf"
    10  	"v2ray.com/core/common/bytespool"
    11  	"v2ray.com/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  }