refine authentication reader

pull/432/head
Darien Raymond 2017-02-06 13:31:36 +01:00
parent a13a8cffd8
commit 47c3646162
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
2 changed files with 34 additions and 27 deletions

View File

@ -2,20 +2,16 @@ package crypto
import ( import (
"crypto/cipher" "crypto/cipher"
"errors"
"io" "io"
"v2ray.com/core/common" "v2ray.com/core/common"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/errors"
"v2ray.com/core/common/serial" "v2ray.com/core/common/serial"
) )
var ( var (
ErrAuthenticationFailed = errors.New("Authentication failed.")
errInsufficientBuffer = errors.New("Insufficient buffer.") errInsufficientBuffer = errors.New("Insufficient buffer.")
errInvalidNonce = errors.New("Invalid nonce.")
errInvalidLength = errors.New("Invalid buffer size.")
) )
type BytesGenerator interface { type BytesGenerator interface {
@ -54,7 +50,7 @@ type AEADAuthenticator struct {
func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) { func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
iv := v.NonceGenerator.Next() iv := v.NonceGenerator.Next()
if len(iv) != v.AEAD.NonceSize() { if len(iv) != v.AEAD.NonceSize() {
return nil, errInvalidNonce return nil, errors.New("Crypto:AEADAuthenticator: Invalid nonce size: ", len(iv))
} }
additionalData := v.AdditionalDataGenerator.Next() additionalData := v.AdditionalDataGenerator.Next()
@ -64,7 +60,7 @@ func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) { func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) {
iv := v.NonceGenerator.Next() iv := v.NonceGenerator.Next()
if len(iv) != v.AEAD.NonceSize() { if len(iv) != v.AEAD.NonceSize() {
return nil, errInvalidNonce return nil, errors.New("Crypto:AEADAuthenticator: Invalid nonce size: ", len(iv))
} }
additionalData := v.AdditionalDataGenerator.Next() additionalData := v.AdditionalDataGenerator.Next()
@ -100,13 +96,13 @@ func (v *AuthenticationReader) NextChunk() error {
return errInsufficientBuffer return errInsufficientBuffer
} }
if size > readerBufferSize-2 { if size > readerBufferSize-2 {
return errInvalidLength return errors.New("Crypto:AuthenticationReader: Size too large: ", size)
} }
if size == v.auth.Overhead() { if size == v.auth.Overhead() {
return io.EOF return io.EOF
} }
if size < v.auth.Overhead() { if size < v.auth.Overhead() {
return errors.New("AuthenticationReader: invalid packet size.") return errors.New("AuthenticationReader: invalid packet size:", size)
} }
cipherChunk := v.buffer.BytesRange(2, size+2) cipherChunk := v.buffer.BytesRange(2, size+2)
plainChunk, err := v.auth.Open(cipherChunk[:0], cipherChunk) plainChunk, err := v.auth.Open(cipherChunk[:0], cipherChunk)
@ -132,26 +128,26 @@ func (v *AuthenticationReader) CopyChunk(b []byte) int {
} }
func (v *AuthenticationReader) EnsureChunk() error { func (v *AuthenticationReader) EnsureChunk() error {
if v.buffer.IsEmpty() {
v.buffer.Clear()
}
for { for {
err := v.NextChunk() err := v.NextChunk()
if err == nil { if err != errInsufficientBuffer {
return nil return err
} }
if err == errInsufficientBuffer {
if v.buffer.IsEmpty() { leftover := v.buffer.Bytes()
v.buffer.Clear() if len(leftover) > 0 {
} else { common.Must(v.buffer.Reset(func(b []byte) (int, error) {
leftover := v.buffer.Bytes() return copy(b, leftover), nil
common.Must(v.buffer.Reset(func(b []byte) (int, error) { }))
return copy(b, leftover), nil }
}))
} if err := v.buffer.AppendSupplier(buf.ReadFrom(v.reader)); err != nil {
err = v.buffer.AppendSupplier(buf.ReadFrom(v.reader)) return err
if err == nil {
continue
}
} }
return err
} }
} }

View File

@ -7,6 +7,8 @@ import (
"io" "io"
"testing" "testing"
"time"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
. "v2ray.com/core/common/crypto" . "v2ray.com/core/common/crypto"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
@ -77,10 +79,10 @@ func TestAuthenticationReaderWriterPartial(t *testing.T) {
payload := make([]byte, 8*1024) payload := make([]byte, 8*1024)
rand.Read(payload) rand.Read(payload)
cache := buf.NewLocal(16 * 1024)
iv := make([]byte, 12) iv := make([]byte, 12)
rand.Read(iv) rand.Read(iv)
cache := buf.NewLocal(16 * 1024)
writer := NewAuthenticationWriter(&AEADAuthenticator{ writer := NewAuthenticationWriter(&AEADAuthenticator{
AEAD: aead, AEAD: aead,
NonceGenerator: &StaticBytesGenerator{ NonceGenerator: &StaticBytesGenerator{
@ -96,13 +98,22 @@ func TestAuthenticationReaderWriterPartial(t *testing.T) {
_, err = writer.Write([]byte{}) _, err = writer.Write([]byte{})
assert.Error(err).IsNil() assert.Error(err).IsNil()
pr, pw := io.Pipe()
go func() {
pw.Write(cache.BytesTo(1024))
time.Sleep(time.Second * 2)
pw.Write(cache.BytesFrom(1024))
time.Sleep(time.Second * 2)
pw.Close()
}()
reader := NewAuthenticationReader(&AEADAuthenticator{ reader := NewAuthenticationReader(&AEADAuthenticator{
AEAD: aead, AEAD: aead,
NonceGenerator: &StaticBytesGenerator{ NonceGenerator: &StaticBytesGenerator{
Content: iv, Content: iv,
}, },
AdditionalDataGenerator: &NoOpBytesGenerator{}, AdditionalDataGenerator: &NoOpBytesGenerator{},
}, cache) }, pr)
actualPayload := make([]byte, 7*1024) actualPayload := make([]byte, 7*1024)
nBytes, err = reader.Read(actualPayload) nBytes, err = reader.Read(actualPayload)