Add crypto dependencies/vendoring
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
committed by
Brandon Lum
parent
b5d0c78225
commit
30c3443947
201
vendor/github.com/miscreant/miscreant-go/pmac/pmac.go
generated
vendored
Normal file
201
vendor/github.com/miscreant/miscreant-go/pmac/pmac.go
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user