Add crypto dependencies/vendoring

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
Stefan Berger
2018-10-03 09:02:59 -04:00
committed by Brandon Lum
parent b5d0c78225
commit 30c3443947
71 changed files with 21809 additions and 0 deletions

201
vendor/github.com/miscreant/miscreant-go/pmac/pmac.go generated vendored Normal file
View File

@@ -0,0 +1,201 @@
// PMAC message authentication code, defined in
// http://web.cs.ucdavis.edu/~rogaway/ocb/pmac.pdf
package pmac
import (
"crypto/cipher"
"crypto/subtle"
"hash"
"math/bits"
"github.com/miscreant/miscreant-go/block"
)
// Number of L blocks to precompute (i.e. µ in the PMAC paper)
// TODO: dynamically compute these as needed
const precomputedBlocks = 31
type pmac struct {
// c is the block cipher we're using (i.e. AES-128 or AES-256)
c cipher.Block
// l is defined as follows (quoted from the PMAC paper):
//
// Equation 1:
//
// a · x =
// a<<1 if firstbit(a)=0
// (a<<1) ⊕ 0¹²⁰10000111 if firstbit(a)=1
//
// Equation 2:
//
// a · x⁻¹ =
// a>>1 if lastbit(a)=0
// (a>>1) ⊕ 10¹²⁰1000011 if lastbit(a)=1
//
// Let L(0) ← L. For i ∈ [1..µ], compute L(i) ← L(i 1) · x by
// Equation (1) using a shift and a conditional xor.
//
// Compute L(1) ← L · x⁻¹ by Equation (2), using a shift and a
// conditional xor.
//
// Save the values L(1), L(0), L(1), L(2), ..., L(µ) in a table.
// (Alternatively, [ed: as we have done in this codebase] defer computing
// some or all of these L(i) values until the value is actually needed.)
l [precomputedBlocks]block.Block
// lInv contains the multiplicative inverse (i.e. right shift) of the first
// l-value, computed as described above, and is XORed into the tag in the
// event the message length is a multiple of the block size
lInv block.Block
// digest contains the PMAC tag-in-progress
digest block.Block
// offset is a block specific tweak to the input message
offset block.Block
// buf contains a part of the input message, processed a block-at-a-time
buf block.Block
// pos marks the end of plaintext in the buf
pos uint
// ctr is the number of blocks we have MAC'd so far
ctr uint
// finished is set true when we are done processing a message, and forbids
// any subsequent writes until we reset the internal state
finished bool
}
// New creates a new PMAC instance using the given cipher
func New(c cipher.Block) hash.Hash {
if c.BlockSize() != block.Size {
panic("pmac: invalid cipher block size")
}
d := new(pmac)
d.c = c
var tmp block.Block
tmp.Encrypt(c)
for i := range d.l {
copy(d.l[i][:], tmp[:])
tmp.Dbl()
}
// Compute L(1) ← L · x⁻¹:
//
// a>>1 if lastbit(a)=0
// (a>>1) ⊕ 10¹²⁰1000011 if lastbit(a)=1
//
copy(tmp[:], d.l[0][:])
lastBit := int(tmp[block.Size-1] & 0x01)
for i := block.Size - 1; i > 0; i-- {
carry := byte(subtle.ConstantTimeSelect(int(tmp[i-1]&1), 0x80, 0))
tmp[i] = (tmp[i] >> 1) | carry
}
tmp[0] >>= 1
tmp[0] ^= byte(subtle.ConstantTimeSelect(lastBit, 0x80, 0))
tmp[block.Size-1] ^= byte(subtle.ConstantTimeSelect(lastBit, block.R>>1, 0))
copy(d.lInv[:], tmp[:])
return d
}
// Reset clears the digest state, starting a new digest.
func (d *pmac) Reset() {
d.digest.Clear()
d.offset.Clear()
d.buf.Clear()
d.pos = 0
d.ctr = 0
d.finished = false
}
// Write adds the given data to the digest state.
func (d *pmac) Write(msg []byte) (int, error) {
if d.finished {
panic("pmac: already finished")
}
var msgPos, msgLen, remaining uint
msgLen = uint(len(msg))
remaining = block.Size - d.pos
// Finish filling the internal buf with the message
if msgLen > remaining {
copy(d.buf[d.pos:], msg[:remaining])
msgPos += remaining
msgLen -= remaining
d.processBuffer()
}
// So long as we have more than a blocks worth of data, compute
// whole-sized blocks at a time.
for msgLen > block.Size {
copy(d.buf[:], msg[msgPos:msgPos+block.Size])
msgPos += block.Size
msgLen -= block.Size
d.processBuffer()
}
if msgLen > 0 {
copy(d.buf[d.pos:d.pos+msgLen], msg[msgPos:])
d.pos += msgLen
}
return len(msg), nil
}
// Sum returns the PMAC digest, one cipher block in length,
// of the data written with Write.
func (d *pmac) Sum(in []byte) []byte {
if d.finished {
panic("pmac: already finished")
}
if d.pos == block.Size {
xor(d.digest[:], d.buf[:])
xor(d.digest[:], d.lInv[:])
} else {
xor(d.digest[:], d.buf[:d.pos])
d.digest[d.pos] ^= 0x80
}
d.digest.Encrypt(d.c)
d.finished = true
return append(in, d.digest[:]...)
}
func (d *pmac) Size() int { return block.Size }
func (d *pmac) BlockSize() int { return block.Size }
// Update the internal tag state based on the buf contents
func (d *pmac) processBuffer() {
xor(d.offset[:], d.l[bits.TrailingZeros(d.ctr+1)][:])
xor(d.buf[:], d.offset[:])
d.ctr++
d.buf.Encrypt(d.c)
xor(d.digest[:], d.buf[:])
d.pos = 0
}
// XOR the contents of b into a in-place
func xor(a, b []byte) {
for i, v := range b {
a[i] ^= v
}
}