diff options
Diffstat (limited to 'oae2.go')
| -rw-r--r-- | oae2.go | 27 |
1 files changed, 20 insertions, 7 deletions
@@ -33,6 +33,11 @@ import ( "math" ) +// ErrInvalid is returned from methods on Reader when the stream failed to +// authenticate. This can indicate that a wrong key was used, or that the data +// was tampered with. +var ErrInvalid = errors.New("invalid stream") + const ( nonceSize = 12 aeadOverhead = 16 @@ -107,7 +112,11 @@ func (e *segmentEncrypter) decryptSegment(segment []byte, lastSegment bool) ([]b if err != nil { return nil, err } - return e.aead.Open(segment[:0], nonce, segment, ad) + plainText, err := e.aead.Open(segment[:0], nonce, segment, ad) + if err != nil { + return nil, fmt.Errorf("%w: %s", ErrInvalid, err) + } + return plainText, nil } // A Writer wraps an io.Writer and encrypts the data in segments. Make sure to @@ -296,8 +305,8 @@ func (r *Reader) initialize() error { r.initialized = true buf := make([]byte, saltSize) if _, r.err = io.ReadFull(&r.r, buf); r.err != nil { - if r.err == io.EOF { - r.err = io.ErrUnexpectedEOF + if r.err == io.EOF || r.err == io.ErrUnexpectedEOF { + r.err = fmt.Errorf("%w: too short", ErrInvalid) } return r.err } @@ -308,7 +317,7 @@ func (r *Reader) initialize() error { // additional data if err := r.fillBuf(); err != nil { if err == io.EOF { - r.err = io.ErrUnexpectedEOF + r.err = fmt.Errorf("%w: too short", ErrInvalid) return r.err } return err @@ -349,7 +358,8 @@ func (r *Reader) fillBuf() error { return nil } -// Read implements io.Reader. +// Read implements io.Reader. Read returns an error wrapping [ErrInvalid] if +// the stream fails authentication. func (r *Reader) Read(buf []byte) (int, error) { if err := r.init(); err != nil { return 0, err @@ -367,7 +377,8 @@ func (r *Reader) Read(buf []byte) (int, error) { return n, nil } -// WriteTo implements io.WriterTo. +// WriteTo implements io.WriterTo. WriteTo returns an error wrapping +// [ErrInvalid] if the stream fails authentication. func (r *Reader) WriteTo(w io.Writer) (int64, error) { if err := r.init(); err != nil { return 0, err @@ -427,7 +438,9 @@ func (r *Reader) seek(offset int64) (int64, error) { } // Seek implements io.Seeker. If the underlying reader does not implement -// io.Seeker, Seek returns [errors.ErrUnsupported]. +// io.Seeker, Seek returns an error wrapping [errors.ErrUnsupported]. Seek may +// also return an error wrapping [ErrInvalid] if the seeked-to segment +// fails authentication. func (r *Reader) Seek(offset int64, whence int) (int64, error) { if _, ok := r.r.r.(io.Seeker); !ok { return 0, fmt.Errorf("%w", errors.ErrUnsupported) |
