Minor refactoring: header checksum now covers _all_ of the header

This commit is contained in:
Sudhi Herle 2019-12-31 11:39:25 -08:00
parent 374daebb8d
commit 262a554356
2 changed files with 48 additions and 24 deletions

View file

@ -10,6 +10,24 @@
// This software does not come with any express or implied // This software does not come with any express or implied
// warranty; it is provided "as is". No claim is made to its // warranty; it is provided "as is". No claim is made to its
// suitability for any purpose. // suitability for any purpose.
//
// Notes
// =====
// Header: Fixed size + Variable list of recipients
// Fixed size header:
// - Magic: 7 bytes
// - Version: 1 byte
// - VLen: 4 byte
//
// Variable Length Segment:
// - Shasum: 32 bytes (SHA256 of full header)
// - Protobuf encoded recipient info
//
// The variable length segment consists of one or more
// recipients, their wrapped keys etc. This is encoded as
// a protobuf message. This protobuf encoded message immediately
// follows the fixed length header.
//
package sign package sign
@ -37,6 +55,7 @@ const EOF uint32 = 1 << 31
const _Magic = "SigTool" const _Magic = "SigTool"
const _MagicLen = len(_Magic) const _MagicLen = len(_Magic)
const _AEADNonceLen = 32 const _AEADNonceLen = 32
const _FixedHdrLen = _MagicLen + 1 + 4
// Encryptor holds the encryption context // Encryptor holds the encryption context
type Encryptor struct { type Encryptor struct {
@ -114,36 +133,35 @@ func (e *Encryptor) AddRecipient(pk *PublicKey) error {
// Begin the encryption process by writing the header // Begin the encryption process by writing the header
func (e *Encryptor) start(wr io.Writer) error { func (e *Encryptor) start(wr io.Writer) error {
msize := e.Size() varHdrLen := sha256.Size + e.Size()
// marshal the header and recipients hdrBuf := make([]byte, _FixedHdrLen + varHdrLen)
hdrlen := _MagicLen + 1 + 4 + sha256.Size
buf := make([]byte, hdrlen+msize) fixedHdr := hdrBuf[:_FixedHdrLen]
hdrbuf := buf[hdrlen:] varHdr := hdrBuf[_FixedHdrLen:]
copy(buf[:], []byte(_Magic)) cksum := varHdr[:sha256.Size]
pbHdr := varHdr[sha256.Size:]
buf[_MagicLen] = 1 // file version# // Now assemble the fixed header
copy(fixedHdr[:], []byte(_Magic))
// The fixed header is the magic _and _ the length of the variable segment. fixedHdr[_MagicLen] = 1 // version #
// So, we capture the length of the variable portion first. binary.BigEndian.PutUint32(fixedHdr[_MagicLen+1:], uint32(varHdrLen))
binary.BigEndian.PutUint32(buf[_MagicLen+1:], uint32(sha256.Size+msize))
// Now marshal the variable portion // Now marshal the variable portion
_, err := e.MarshalToSizedBuffer(hdrbuf) _, err := e.MarshalToSizedBuffer(pbHdr)
if err != nil { if err != nil {
return fmt.Errorf("encrypt: can't marshal header: %s", err) return fmt.Errorf("encrypt: can't marshal header: %s", err)
} }
// and calculate the header checksum // Now calculate checksum of everything
cksum := buf[_MagicLen+1+4:]
h := sha256.New() h := sha256.New()
h.Write(hdrbuf) h.Write(fixedHdr)
h.Write(pbHdr)
h.Sum(cksum[:0]) h.Sum(cksum[:0])
// Finally write it out // Finally write it out
err = fullwrite(buf, wr) err = fullwrite(hdrBuf, wr)
if err != nil { if err != nil {
return fmt.Errorf("encrypt: %s", err) return fmt.Errorf("encrypt: %s", err)
} }
@ -252,7 +270,7 @@ type Decryptor struct {
// Create a new decryption context and if 'pk' is given, check that it matches // Create a new decryption context and if 'pk' is given, check that it matches
// the sender // the sender
func NewDecryptor(rd io.Reader) (*Decryptor, error) { func NewDecryptor(rd io.Reader) (*Decryptor, error) {
var b [12]byte var b [_FixedHdrLen]byte
_, err := io.ReadFull(rd, b[:]) _, err := io.ReadFull(rd, b[:])
if err != nil { if err != nil {
@ -268,8 +286,10 @@ func NewDecryptor(rd io.Reader) (*Decryptor, error) {
} }
hdrlen := binary.BigEndian.Uint32(b[_MagicLen+1:]) hdrlen := binary.BigEndian.Uint32(b[_MagicLen+1:])
if hdrlen > 65536 {
return nil, fmt.Errorf("decrypt: header too large (max 65536)") // sanity check on variable segment length
if hdrlen > 1048576 {
return nil, fmt.Errorf("decrypt: header too large (max 1048576)")
} }
if hdrlen < 32 { if hdrlen < 32 {
return nil, fmt.Errorf("decrypt: header too small (min 32)") return nil, fmt.Errorf("decrypt: header too small (min 32)")
@ -282,10 +302,14 @@ func NewDecryptor(rd io.Reader) (*Decryptor, error) {
return nil, fmt.Errorf("decrypt: err while reading header: %s", err) return nil, fmt.Errorf("decrypt: err while reading header: %s", err)
} }
verify := hdr[:32] verify := hdr[:sha256.Size]
hdr = hdr[32:] pbHdr := hdr[sha256.Size:]
h := sha256.New()
h.Write(b[:])
h.Write(pbHdr)
cksum := h.Sum(nil)
cksum := sha256.Sum256(hdr)
if subtle.ConstantTimeCompare(verify, cksum[:]) == 0 { if subtle.ConstantTimeCompare(verify, cksum[:]) == 0 {
return nil, fmt.Errorf("decrypt: header corrupted") return nil, fmt.Errorf("decrypt: header corrupted")
} }
@ -294,7 +318,7 @@ func NewDecryptor(rd io.Reader) (*Decryptor, error) {
rd: rd, rd: rd,
} }
err = d.Header.Unmarshal(hdr) err = d.Header.Unmarshal(pbHdr)
if err != nil { if err != nil {
return nil, fmt.Errorf("decrypt: decode error: %s", err) return nil, fmt.Errorf("decrypt: decode error: %s", err)
} }

View file

@ -1 +1 @@
0.6.1 0.6.2