// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// EAX mode, not a NIST standard (yet).
// EAX provides encryption and authentication.
// EAX targets the same uses as NIST's CCM mode,
// but EAX adds the ability to run in streaming mode.

// See
// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf
// http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
// What those papers call OMAC is now called CMAC.

package block

import (
	"fmt"
	"hash"
	"io"
	"os"
)

// An EAXTagError is returned when the message has failed to authenticate,
// because the tag at the end of the message stream (Read) does not match
// the tag computed from the message itself (Computed).
type EAXTagError struct {
	Read     []byte
	Computed []byte
}

func (e *EAXTagError) String() string {
	return fmt.Sprintf("crypto/block: EAX tag mismatch: read %x but computed %x", e.Read, e.Computed)
}

func setupEAX(c Cipher, iv, hdr []byte, tagBytes int) (ctrIV, tag []byte, cmac hash.Hash) {
	n := len(iv)
	if n != c.BlockSize() {
		panicln("crypto/block: EAX: iv length", n, "!=", c.BlockSize())
	}
	buf := make([]byte, n) // zeroed

	// tag = CMAC(0 + iv) ^ CMAC(1 + hdr) ^ CMAC(2 + data)
	cmac = NewCMAC(c)
	cmac.Write(buf) // 0
	cmac.Write(iv)
	sum := cmac.Sum()
	ctrIV = copy(sum)
	tag = copy(sum[0:tagBytes])

	cmac.Reset()
	buf[n-1] = 1
	cmac.Write(buf) // 1
	cmac.Write(hdr)
	sum = cmac.Sum()
	for i := 0; i < tagBytes; i++ {
		tag[i] ^= sum[i]
	}

	cmac.Reset()
	buf[n-1] = 2 // 2
	cmac.Write(buf)

	return
}

func finishEAX(tag []byte, cmac hash.Hash) {
	// Finish CMAC #2 and xor into tag.
	sum := cmac.Sum()
	for i := range tag {
		tag[i] ^= sum[i]
	}
}

// Writer adapter.  Tees writes into both w and cmac.
// Knows that cmac never returns write errors.
type cmacWriter struct {
	w    io.Writer
	cmac hash.Hash
}

func (cw *cmacWriter) Write(p []byte) (n int, err os.Error) {
	n, err = cw.w.Write(p)
	cw.cmac.Write(p[0:n])
	return
}

// An eaxEncrypter implements the EAX encryption mode.
type eaxEncrypter struct {
	ctr io.Writer  // CTR encrypter
	cw  cmacWriter // CTR's output stream
	tag []byte
}

// NewEAXEncrypter creates and returns a new EAX encrypter
// using the given cipher c, initialization vector iv, associated data hdr,
// and tag length tagBytes.  The encrypter's Write method encrypts
// the data it receives and writes that data to w.
// The encrypter's Close method writes a final authenticating tag to w.
func NewEAXEncrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, w io.Writer) io.WriteCloser {
	x := new(eaxEncrypter)

	// Create new CTR instance writing to both
	// w for encrypted output and cmac for digesting.
	x.cw.w = w
	var ctrIV []byte
	ctrIV, x.tag, x.cw.cmac = setupEAX(c, iv, hdr, tagBytes)
	x.ctr = NewCTRWriter(c, ctrIV, &x.cw)
	return x
}

func (x *eaxEncrypter) Write(p []byte) (n int, err os.Error) {
	return x.ctr.Write(p)
}

func (x *eaxEncrypter) Close() os.Error {
	x.ctr = nil // crash if Write is called again

	// Write tag.
	finishEAX(x.tag, x.cw.cmac)
	n, err := x.cw.w.Write(x.tag)
	if n != len(x.tag) && err == nil {
		err = io.ErrShortWrite
	}

	return err
}

// Reader adapter.  Returns data read from r but hangs
// on to the last len(tag) bytes for itself (returns EOF len(tag)
// bytes early).  Also tees all data returned from Read into
// the cmac digest.  The "don't return the last t bytes"
// and the "tee into digest" functionality could be separated,
// but the latter half is trivial.
type cmacReader struct {
	r    io.Reader
	cmac hash.Hash
	tag  []byte
	tmp  []byte
}

func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
	// TODO(rsc): Maybe fall back to simpler code if
	// we recognize the underlying r as a ByteBuffer
	// or ByteReader.  Then we can just take the last piece
	// off at the start.

	// First, read a tag-sized chunk.
	// It's probably not the tag (unless there's no data).
	tag := cr.tag
	if len(tag) < cap(tag) {
		nt := len(tag)
		nn, err1 := io.ReadFull(cr.r, tag[nt:cap(tag)])
		tag = tag[0 : nt+nn]
		cr.tag = tag
		if err1 != nil {
			return 0, err1
		}
	}

	tagBytes := len(tag)
	if len(p) > 4*tagBytes {
		// If p is big, try to read directly into p to avoid a copy.
		n, err = cr.r.Read(p[tagBytes:])
		if n == 0 {
			goto out
		}
		// copy old tag into p
		for i := 0; i < tagBytes; i++ {
			p[i] = tag[i]
		}
		// copy new tag out of p
		for i := 0; i < tagBytes; i++ {
			tag[i] = p[n+i]
		}
		goto out
	}

	// Otherwise, read into p and then slide data
	n, err = cr.r.Read(p)
	if n == 0 {
		goto out
	}

	// copy tag+p into p+tmp and then swap tmp, tag
	tmp := cr.tmp
	for i := n + tagBytes - 1; i >= 0; i-- {
		var c byte
		if i < tagBytes {
			c = tag[i]
		} else {
			c = p[i-tagBytes]
		}
		if i < n {
			p[i] = c
		} else {
			tmp[i] = c
		}
	}
	cr.tmp, cr.tag = tag, tmp

out:
	cr.cmac.Write(p[0:n])
	return
}

type eaxDecrypter struct {
	ctr io.Reader
	cr  cmacReader
	tag []byte
}

// NewEAXDecrypter creates and returns a new EAX decrypter
// using the given cipher c, initialization vector iv, associated data hdr,
// and tag length tagBytes.  The encrypter's Read method decrypts and
// returns data read from r.  At r's EOF, the encrypter checks the final
// authenticating tag and returns an EAXTagError if the tag is invalid.
// In that case, the message should be discarded.
// Note that the data stream returned from Read cannot be
// assumed to be valid, authenticated data until Read returns
// 0, nil to signal the end of the data.
func NewEAXDecrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, r io.Reader) io.Reader {
	x := new(eaxDecrypter)

	x.cr.r = r
	x.cr.tag = make([]byte, 0, tagBytes)
	x.cr.tmp = make([]byte, 0, tagBytes)
	var ctrIV []byte
	ctrIV, x.tag, x.cr.cmac = setupEAX(c, iv, hdr, tagBytes)
	x.ctr = NewCTRReader(c, ctrIV, &x.cr)
	return x
}

func (x *eaxDecrypter) checkTag() os.Error {
	x.ctr = nil // crash if Read is called again

	finishEAX(x.tag, x.cr.cmac)
	if !same(x.tag, x.cr.tag) {
		e := new(EAXTagError)
		e.Computed = copy(x.tag)
		e.Read = copy(x.cr.tag)
		return e
	}
	return nil
}

func (x *eaxDecrypter) Read(p []byte) (n int, err os.Error) {
	n, err = x.ctr.Read(p)
	if n == 0 && err == nil {
		err = x.checkTag()
	}
	return n, err
}
