added fs encryption overlay

This commit is contained in:
ston1th 2022-04-06 01:08:19 +02:00
commit fd1e8118a4
28 changed files with 3994 additions and 30 deletions

View file

@ -0,0 +1,107 @@
package crypto
import (
"crypto/cipher"
"errors"
"io"
"golang.org/x/crypto/chacha20poly1305"
)
type cryptoReader interface {
io.Reader
io.ReaderAt
}
type reader struct {
a cipher.AEAD
src cryptoReader
unread []byte // decrypted but unread data, backed by buf
buf [FullSize]byte
off int64
err error
nonce [NonceSize]byte
}
func newReader(key []byte, src cryptoReader) (*reader, error) {
aead, err := chacha20poly1305.New(key)
if err != nil {
return nil, err
}
return &reader{
a: aead,
src: src,
}, nil
}
func (r *reader) Read(p []byte) (int, error) {
if len(r.unread) > 0 {
n := copy(p, r.unread)
r.unread = r.unread[n:]
return n, nil
}
if r.err != nil {
return 0, r.err
}
if len(p) == 0 {
return 0, nil
}
last, err := r.readChunk()
if err != nil {
r.err = err
return 0, err
}
if r.off > 0 && len(r.unread) >= int(r.off) {
r.unread = r.unread[r.off:]
r.off = 0
}
n := copy(p, r.unread)
r.unread = r.unread[n:]
if last {
r.err = io.EOF
}
return n, nil
}
func (r *reader) readChunk() (last bool, err error) {
if len(r.unread) != 0 {
panic("stream: internal error: readChunk called with dirty buffer")
}
in := r.buf[:]
n, err := io.ReadFull(r.src, in)
switch {
case err == io.EOF:
// A message can't end without a marked chunk. This message is truncated.
return false, io.ErrUnexpectedEOF
case err == io.ErrUnexpectedEOF:
// The last chunk can be short.
in = in[:n]
last = true
setLastChunkFlag(&r.nonce)
case err != nil:
return false, err
}
outBuf := make([]byte, 0, ChunkSize)
out, err := r.a.Open(outBuf, r.nonce[:], in, nil)
if err != nil && !last {
// Check if this was a full-length final chunk.
last = true
setLastChunkFlag(&r.nonce)
out, err = r.a.Open(outBuf, r.nonce[:], in, nil)
}
if err != nil {
return false, errors.New("failed to decrypt and authenticate payload chunk")
}
incNonce(&r.nonce)
r.unread = r.buf[:copy(r.buf[:], out)]
return last, nil
}