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

25
vendor/github.com/miscreant/miscreant-go/LICENSE.txt generated vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2017-2018 The Miscreant Developers. The canonical list of project
contributors who hold copyright over the project can be found at:
https://github.com/miscreant/miscreant/blob/master/AUTHORS.md
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

95
vendor/github.com/miscreant/miscreant-go/README.md generated vendored Normal file
View File

@@ -0,0 +1,95 @@
# miscreant.go [![Build Status][build-shield]][build-link] [![GoDoc][godoc-shield]][godoc-link] [![Go Report Card][goreport-shield]][goreport-link] [![MIT licensed][license-shield]][license-link] [![Gitter Chat][gitter-image]][gitter-link]
> The best crypto you've never heard of, brought to you by [Phil Rogaway]
Go implementation of **Miscreant**: Advanced symmetric encryption library
which provides the [AES-SIV] ([RFC 5297]), [AES-PMAC-SIV], and [STREAM]
constructions. These algorithms are easy-to-use (or rather, hard-to-misuse)
and support encryption of individual messages or message streams.
```go
import "github.com/miscreant/miscreant-go"
```
All types are designed to be **thread-compatible**: Methods of an instance shared between
multiple threads (or goroutines) must not be accessed concurrently. Callers are responsible for
implementing their own mutual exclusion.
- [Documentation] (Wiki)
- [godoc][godoc-link]
## About AES-SIV and AES-PMAC-SIV
**AES-SIV** and **AES-PMAC-SIV** provide [nonce-reuse misuse-resistance] (NRMR):
accidentally reusing a nonce with this construction is not a security
catastrophe, unlike more popular AES encryption modes like [AES-GCM] where
nonce reuse leaks both the authentication key and the XOR of both plaintexts,
both of which can potentially be leveraged for *full plaintext recovery attacks*.
With **AES-SIV**, the worst outcome of reusing a nonce is an attacker
can see you've sent the same plaintext twice, as opposed to almost all other
AES modes where it can facilitate [chosen ciphertext attacks] and/or
full plaintext recovery.
## Help and Discussion
Have questions? Want to suggest a feature or change?
* [Gitter]: web-based chat about miscreant projects including **miscreant.go**
* [Google Group]: join via web or email ([miscreant-crypto+subscribe@googlegroups.com])
## Security Notice
Though this library is written by cryptographic professionals, it has not
undergone a thorough security audit, and cryptographic professionals are still
humans that make mistakes.
This library makes an effort to use constant time operations throughout its
implementation, however actual constant time behavior has not been verified.
Use this library at your own risk.
## Code of Conduct
We abide by the [Contributor Covenant][cc] and ask that you do as well.
For more information, please see [CODE_OF_CONDUCT.md].
## Contributing
Bug reports and pull requests are welcome on GitHub at:
<https://github.com/miscreant/miscreant-go>
## Copyright
Copyright (c) 2017-2018 [The Miscreant Developers][AUTHORS].
See [LICENSE.txt] for further details.
[build-shield]: https://secure.travis-ci.org/miscreant/miscreant-go.svg?branch=master
[build-link]: https://travis-ci.org/miscreant/miscreant-go
[godoc-shield]: https://godoc.org/github.com/miscreant/miscreant-go?status.svg
[godoc-link]: https://godoc.org/github.com/miscreant/miscreant-go
[goreport-shield]: https://goreportcard.com/badge/github.com/miscreant/miscreant-go
[goreport-link]: https://goreportcard.com/report/github.com/miscreant/miscreant-go
[license-shield]: https://img.shields.io/badge/license-MIT-blue.svg
[license-link]: https://github.com/miscreant/miscreant-go/blob/master/LICENSE.txt
[gitter-image]: https://badges.gitter.im/badge.svg
[gitter-link]: https://gitter.im/miscreant/Lobby
[Phil Rogaway]: https://en.wikipedia.org/wiki/Phillip_Rogaway
[AES-SIV]: https://github.com/miscreant/miscreant/wiki/AES-SIV
[RFC 5297]: https://tools.ietf.org/html/rfc5297
[AES-PMAC-SIV]: https://github.com/miscreant/miscreant/wiki/AES-PMAC-SIV
[STREAM]: https://github.com/miscreant/miscreant/wiki/STREAM
[nonce-reuse misuse-resistance]: https://github.com/miscreant/miscreant/wiki/Nonce-Reuse-Misuse-Resistance
[AES-GCM]: https://en.wikipedia.org/wiki/Galois/Counter_Mode
[chosen ciphertext attacks]: https://en.wikipedia.org/wiki/Chosen-ciphertext_attack
[Documentation]: https://github.com/miscreant/miscreant/wiki/Go-Documentation
[Gitter]: https://gitter.im/miscreant/Lobby
[Google Group]: https://groups.google.com/forum/#!forum/miscreant-crypto
[miscreant-crypto+subscribe@googlegroups.com]: mailto:miscreant-crypto+subscribe@googlegroups.com?subject=subscribe
[cc]: https://contributor-covenant.org
[CODE_OF_CONDUCT.md]: https://github.com/miscreant/miscreant-go/blob/master/CODE_OF_CONDUCT.md
[AUTHORS]: https://github.com/miscreant/miscreant-go/blob/master/AUTHORS.md
[LICENSE.txt]: https://github.com/miscreant/miscreant-go/blob/master/LICENSE.txt

108
vendor/github.com/miscreant/miscreant-go/aead.go generated vendored Normal file
View File

@@ -0,0 +1,108 @@
// Written in 2015 by Dmitry Chestnykh.
package miscreant
import (
"crypto/cipher"
"crypto/rand"
"io"
)
// Minimum nonce size for which we'll allow the generation of random nonces
const minimumRandomNonceSize = 16
// aead is a wrapper for Cipher implementing cipher.AEAD interface.
type aead struct {
// miscreant.Cipher instance underlying this AEAD
c *Cipher
// Size of the nonce required
nonceSize int
}
// GenerateKey generates a random 32-byte or 64-byte encryption key.
// Panics if the key size is unsupported or source of randomness fails.
func GenerateKey(length int) []byte {
if length != 32 && length != 64 {
panic("miscreant.GenerateKey: invalid key size: " + string(length))
}
key := make([]byte, length)
_, err := io.ReadFull(rand.Reader, key[:])
if err != nil {
panic(err)
}
return key
}
// GenerateNonce generates a random nonce for the given `cipher.AEAD`.
// Panics if the configured nonce size is less than 16-bytes (128-bits)
func GenerateNonce(c cipher.AEAD) []byte {
if c.NonceSize() < minimumRandomNonceSize {
panic("miscreant.GenerateNonce: nonce size is too small: " + string(c.NonceSize()))
}
nonce := make([]byte, c.NonceSize())
_, err := io.ReadFull(rand.Reader, nonce[:])
if err != nil {
panic(err)
}
return nonce
}
// NewAEAD returns an AES-SIV instance implementing cipher.AEAD interface,
// with the given cipher, nonce size, and a key which must be twice as long
// as an AES key, either 32 or 64 bytes to select AES-128 (AES-SIV-256)
// or AES-256 (AES-SIV-512).
//
// Unless the given nonce size is less than zero, Seal and Open will panic when
// passed nonce of a different size.
func NewAEAD(alg string, key []byte, nonceSize int) (cipher.AEAD, error) {
switch alg {
case "AES-SIV", "AES-CMAC-SIV":
c, err := NewAESCMACSIV(key)
if err != nil {
return nil, err
}
return &aead{c: c, nonceSize: nonceSize}, nil
case "AES-PMAC-SIV":
c, err := NewAESPMACSIV(key)
if err != nil {
return nil, err
}
return &aead{c: c, nonceSize: nonceSize}, nil
default:
panic("NewAEAD: unknown cipher: " + alg)
}
}
func (a *aead) NonceSize() int { return a.nonceSize }
func (a *aead) Overhead() int { return a.c.Overhead() }
func (a *aead) Seal(dst, nonce, plaintext, data []byte) (out []byte) {
if len(nonce) != a.nonceSize && a.nonceSize >= 0 {
panic("miscreant.AEAD: incorrect nonce length")
}
var err error
if data == nil {
out, err = a.c.Seal(dst, plaintext, nonce)
} else {
out, err = a.c.Seal(dst, plaintext, data, nonce)
}
if err != nil {
panic("miscreant.AEAD: " + err.Error())
}
return out
}
func (a *aead) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(nonce) != a.nonceSize && a.nonceSize >= 0 {
panic("miscreant.AEAD: incorrect nonce length")
}
if data == nil {
return a.c.Open(dst, ciphertext, nonce)
}
return a.c.Open(dst, ciphertext, data, nonce)
}

View File

@@ -0,0 +1,49 @@
// Common block cipher functionality shared across this library
package block
import (
"crypto/cipher"
"crypto/subtle"
)
const (
// Size of an AES block in bytes
Size = 16
// R is the minimal irreducible polynomial for a 128-bit block size
R = 0x87
)
// Block is a 128-bit array used by certain block ciphers (i.e. AES)
type Block [Size]byte
// Clear zeroes out the contents of the block
func (b *Block) Clear() {
// TODO: use a more secure zeroing method that won't be optimized away
for i := range b {
b[i] = 0
}
}
// Dbl performs a doubling of a block over GF(2^128):
//
// a<<1 if firstbit(a)=0
// (a<<1) ⊕ 0¹²⁰10000111 if firstbit(a)=1
//
func (b *Block) Dbl() {
var z byte
for i := Size - 1; i >= 0; i-- {
zz := b[i] >> 7
b[i] = b[i]<<1 | z
z = zz
}
b[Size-1] ^= byte(subtle.ConstantTimeSelect(int(z), R, 0))
}
// Encrypt a block with the given block cipher
func (b *Block) Encrypt(c cipher.Block) {
c.Encrypt(b[:], b[:])
}

114
vendor/github.com/miscreant/miscreant-go/cmac/cmac.go generated vendored Normal file
View File

@@ -0,0 +1,114 @@
// 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.
// CMAC message authentication code, defined in
// NIST Special Publication SP 800-38B.
package cmac
import (
"crypto/cipher"
"hash"
"github.com/miscreant/miscreant-go/block"
)
type cmac struct {
// c is the block cipher we're using (i.e. AES-128 or AES-256)
c cipher.Block
// k1 and k2 are CMAC subkeys (for finishing the tag)
k1, k2 block.Block
// digest contains the PMAC tag-in-progress
digest block.Block
// buffer contains a part of the input message, processed a block-at-a-time
buf block.Block
// pos marks the end of plaintext in the buffer
pos uint
}
// New returns a new instance of a CMAC message authentication code
// digest using the given cipher.Block.
func New(c cipher.Block) hash.Hash {
if c.BlockSize() != block.Size {
panic("pmac: invalid cipher block size")
}
d := new(cmac)
d.c = c
// Subkey generation, p. 7
d.k1.Encrypt(c)
d.k1.Dbl()
copy(d.k2[:], d.k1[:])
d.k2.Dbl()
return d
}
// Reset clears the digest state, starting a new digest.
func (d *cmac) Reset() {
d.digest.Clear()
d.buf.Clear()
d.pos = 0
}
// Write adds the given data to the digest state.
func (d *cmac) Write(p []byte) (nn int, err error) {
nn = len(p)
left := block.Size - d.pos
if uint(len(p)) > left {
xor(d.buf[d.pos:], p[:left])
p = p[left:]
d.buf.Encrypt(d.c)
d.pos = 0
}
for uint(len(p)) > block.Size {
xor(d.buf[:], p[:block.Size])
p = p[block.Size:]
d.buf.Encrypt(d.c)
}
if len(p) > 0 {
xor(d.buf[d.pos:], p)
d.pos += uint(len(p))
}
return
}
// Sum returns the CMAC digest, one cipher block in length,
// of the data written with Write.
func (d *cmac) Sum(in []byte) []byte {
// Finish last block, mix in key, encrypt.
// Don't edit ci, in case caller wants
// to keep digesting after call to Sum.
k := d.k1
if d.pos < uint(len(d.digest)) {
k = d.k2
}
for i := 0; i < len(d.buf); i++ {
d.digest[i] = d.buf[i] ^ k[i]
}
if d.pos < uint(len(d.digest)) {
d.digest[d.pos] ^= 0x80
}
d.digest.Encrypt(d.c)
return append(in, d.digest[:]...)
}
func (d *cmac) Size() int { return len(d.digest) }
func (d *cmac) BlockSize() int { return d.c.BlockSize() }
func xor(a, b []byte) {
for i, v := range b {
a[i] ^= v
}
}

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
}
}

243
vendor/github.com/miscreant/miscreant-go/siv.go generated vendored Normal file
View File

@@ -0,0 +1,243 @@
// Originally written in 2015 by Dmitry Chestnykh.
// Modified in 2017 by Tony Arcieri.
//
// Miscreant implements Synthetic Initialization Vector (SIV)-based
// authenticated encryption using the AES block cipher (RFC 5297).
package miscreant
import (
"crypto/aes"
"crypto/cipher"
"crypto/subtle"
"errors"
"github.com/miscreant/miscreant-go/block"
"github.com/miscreant/miscreant-go/cmac"
"github.com/miscreant/miscreant-go/pmac"
"hash"
)
// MaxAssociatedDataItems is the maximum number of associated data items
const MaxAssociatedDataItems = 126
var (
// ErrKeySize indicates the given key size is not supported
ErrKeySize = errors.New("siv: bad key size")
// ErrNotAuthentic indicates a ciphertext is malformed or corrupt
ErrNotAuthentic = errors.New("siv: authentication failed")
// ErrTooManyAssociatedDataItems indicates more than MaxAssociatedDataItems were given
ErrTooManyAssociatedDataItems = errors.New("siv: too many associated data items")
)
// Cipher is an instance of AES-SIV, configured with either AES-CMAC or
// AES-PMAC as a message authentication code.
type Cipher struct {
// MAC function used to derive a synthetic IV and authenticate the message
h hash.Hash
// Block cipher function used to encrypt the message
b cipher.Block
// Internal buffers
tmp1, tmp2 block.Block
}
// NewAESCMACSIV returns a new AES-SIV cipher with the given key, which must be
// twice as long as an AES key, either 32 or 64 bytes to select AES-128
// (AES-CMAC-SIV-256), or AES-256 (AES-CMAC-SIV-512).
func NewAESCMACSIV(key []byte) (c *Cipher, err error) {
n := len(key)
if n != 32 && n != 64 {
return nil, ErrKeySize
}
macBlock, err := aes.NewCipher(key[:n/2])
if err != nil {
return nil, err
}
ctrBlock, err := aes.NewCipher(key[n/2:])
if err != nil {
return nil, err
}
c = new(Cipher)
c.h = cmac.New(macBlock)
c.b = ctrBlock
return c, nil
}
// NewAESPMACSIV returns a new AES-SIV cipher with the given key, which must be
// twice as long as an AES key, either 32 or 64 bytes to select AES-128
// (AES-PMAC-SIV-256), or AES-256 (AES-PMAC-SIV-512).
func NewAESPMACSIV(key []byte) (c *Cipher, err error) {
n := len(key)
if n != 32 && n != 64 {
return nil, ErrKeySize
}
macBlock, err := aes.NewCipher(key[:n/2])
if err != nil {
return nil, err
}
ctrBlock, err := aes.NewCipher(key[n/2:])
if err != nil {
return nil, err
}
c = new(Cipher)
c.h = pmac.New(macBlock)
c.b = ctrBlock
return c, nil
}
// Overhead returns the difference between plaintext and ciphertext lengths.
func (c *Cipher) Overhead() int {
return c.h.Size()
}
// Seal encrypts and authenticates plaintext, authenticates the given
// associated data items, and appends the result to dst, returning the updated
// slice.
//
// The plaintext and dst may alias exactly or not at all.
//
// For nonce-based encryption, the nonce should be the last associated data item.
func (c *Cipher) Seal(dst []byte, plaintext []byte, data ...[]byte) ([]byte, error) {
if len(data) > MaxAssociatedDataItems {
return nil, ErrTooManyAssociatedDataItems
}
// Authenticate
iv := c.s2v(data, plaintext)
ret, out := sliceForAppend(dst, len(iv)+len(plaintext))
copy(out, iv)
// Encrypt
zeroIVBits(iv)
ctr := cipher.NewCTR(c.b, iv)
ctr.XORKeyStream(out[len(iv):], plaintext)
return ret, nil
}
// Open decrypts ciphertext, authenticates the decrypted plaintext and the given
// associated data items and, if successful, appends the resulting plaintext
// to dst, returning the updated slice. The additional data items must match the
// items passed to Seal.
//
// The ciphertext and dst may alias exactly or not at all.
//
// For nonce-based encryption, the nonce should be the last associated data item.
func (c *Cipher) Open(dst []byte, ciphertext []byte, data ...[]byte) ([]byte, error) {
if len(data) > MaxAssociatedDataItems {
return nil, ErrTooManyAssociatedDataItems
}
if len(ciphertext) < c.Overhead() {
return nil, ErrNotAuthentic
}
// Decrypt
iv := c.tmp1[:c.Overhead()]
copy(iv, ciphertext)
zeroIVBits(iv)
ctr := cipher.NewCTR(c.b, iv)
ret, out := sliceForAppend(dst, len(ciphertext)-len(iv))
ctr.XORKeyStream(out, ciphertext[len(iv):])
// Authenticate
expected := c.s2v(data, out)
if subtle.ConstantTimeCompare(ciphertext[:len(iv)], expected) != 1 {
return nil, ErrNotAuthentic
}
return ret, nil
}
func (c *Cipher) s2v(s [][]byte, sn []byte) []byte {
h := c.h
h.Reset()
tmp, d := c.tmp1, c.tmp2
tmp.Clear()
// NOTE(dchest): The standalone S2V returns CMAC(1) if the number of
// passed vectors is zero, however in SIV construction this case is
// never triggered, since we always pass plaintext as the last vector
// (even if it's zero-length), so we omit this case.
_, err := h.Write(tmp[:])
if err != nil {
panic(err)
}
copy(d[:], h.Sum(d[:0]))
h.Reset()
for _, v := range s {
_, err := h.Write(v)
if err != nil {
panic(err)
}
copy(tmp[:], h.Sum(tmp[:0]))
h.Reset()
d.Dbl()
xor(d[:], tmp[:])
}
tmp.Clear()
if len(sn) >= h.BlockSize() {
n := len(sn) - len(d)
copy(tmp[:], sn[n:])
_, err = h.Write(sn[:n])
if err != nil {
panic(err)
}
} else {
copy(tmp[:], sn)
tmp[len(sn)] = 0x80
d.Dbl()
}
xor(tmp[:], d[:])
_, err = h.Write(tmp[:])
if err != nil {
panic(err)
}
return h.Sum(tmp[:0])
}
func xor(a, b []byte) {
for i, v := range b {
a[i] ^= v
}
}
func zeroIVBits(iv []byte) {
// "We zero-out the top bit in each of the last two 32-bit words
// of the IV before assigning it to Ctr"
// — http://web.cs.ucdavis.edu/~rogaway/papers/siv.pdf
iv[len(iv)-8] &= 0x7f
iv[len(iv)-4] &= 0x7f
}
// sliceForAppend takes a slice and a requested number of bytes. It returns a
// slice with the contents of the given slice followed by that many bytes and a
// second slice that aliases into it and contains only the extra bytes. If the
// original slice has sufficient capacity then no allocation is performed.
func sliceForAppend(in []byte, n int) (head, tail []byte) {
if total := len(in) + n; cap(in) >= total {
head = in[:total]
} else {
head = make([]byte, total)
copy(head, in)
}
tail = head[len(in):]
return
}

173
vendor/github.com/miscreant/miscreant-go/stream.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
package miscreant
import (
"crypto/cipher"
"encoding/binary"
)
// streamNoncePrefixSize is the user-supplied nonce size
const streamNoncePrefixSize = 8
// streamExtendedNonceSize is the nonce prefix + 32-bit counter + 1-byte last block flag
const streamExtendedNonceSize = streamNoncePrefixSize + 4 + 1
// lastBlockFlag indicates that a block is the last in the STREAM
const lastBlockFlag byte = 1
// counterMax is the maximum allowable value for the stream counter
const counterMax uint64 = 0xFFFFFFFF
// StreamEncryptor encrypts message streams, selecting the nonces using a
// 32-bit counter, generalized for any cipher.AEAD algorithm
//
// This construction corresponds to the stream encryptor object as defined in
// the paper Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
type StreamEncryptor struct {
// cipher.AEAD instance underlying this STREAM
a cipher.AEAD
// Nonce encoder instance which computes per-message nonces
n *nonceEncoder32
}
// NewStreamEncryptor returns a STREAM encryptor instance with the given
// cipher, nonce, and a key which must be twice as long as an AES key, either
// 32 or 64 bytes to select AES-128 (AES-SIV-256) or AES-256 (AES-SIV-512).
func NewStreamEncryptor(alg string, key, nonce []byte) (*StreamEncryptor, error) {
aead, err := NewAEAD(alg, key, streamExtendedNonceSize)
if err != nil {
return nil, err
}
nonceEncoder, err := newNonceEncoder32(nonce)
if err != nil {
return nil, err
}
return &StreamEncryptor{a: aead, n: nonceEncoder}, nil
}
// NonceSize returns the size of the nonce that must be passed to
// NewStreamEncryptor
func (e *StreamEncryptor) NonceSize() int { return streamNoncePrefixSize }
// Overhead returns the maximum difference between the lengths of a
// plaintext and its ciphertext, which in the case of AES-SIV modes
// is the size of the initialization vector
func (e *StreamEncryptor) Overhead() int { return e.a.Overhead() }
// Seal the next message in the STREAM, which encrypts and authenticates
// plaintext, authenticates the additional data and appends the result to dst,
// returning the updated slice.
//
// The plaintext and dst may alias exactly or not at all. To reuse
// plaintext's storage for the encrypted output, use plaintext[:0] as dst.
//
// The lastBlock argument should be set to true if this is the last message
// in the STREAM. No further messages can be encrypted after the last one
func (e *StreamEncryptor) Seal(dst, plaintext, aData []byte, lastBlock bool) []byte {
return e.a.Seal(dst, e.n.Next(lastBlock), plaintext, aData)
}
// StreamDecryptor decrypts message streams, selecting the nonces using a
// 32-bit counter, generalized for any cipher.AEAD algorithm
//
// This construction corresponds to the stream encryptor object as defined in
// the paper Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
type StreamDecryptor struct {
// cipher.AEAD instance underlying this STREAM
a cipher.AEAD
// Nonce encoder instance which computes per-message nonces
n *nonceEncoder32
}
// NewStreamDecryptor returns a STREAM encryptor instance with the given
// cipher, nonce, and a key which must be twice as long as an AES key, either
// 32 or 64 bytes to select AES-128 (AES-SIV-256) or AES-256 (AES-SIV-512).
func NewStreamDecryptor(alg string, key, nonce []byte) (*StreamDecryptor, error) {
aead, err := NewAEAD(alg, key, streamExtendedNonceSize)
if err != nil {
return nil, err
}
nonceEncoder, err := newNonceEncoder32(nonce)
if err != nil {
return nil, err
}
return &StreamDecryptor{a: aead, n: nonceEncoder}, nil
}
// NonceSize returns the size of the nonce that must be passed to
// NewStreamDecryptor
func (d *StreamDecryptor) NonceSize() int { return streamNoncePrefixSize }
// Overhead returns the maximum difference between the lengths of a
// plaintext and its ciphertext, which in the case of AES-SIV modes
// is the size of the initialization vector
func (d *StreamDecryptor) Overhead() int { return d.a.Overhead() }
// Open decrypts and authenticates the next ciphertext in the STREAM,
// and also authenticates the additional data, ensuring it matches
// the value passed to Seal.
//
// If successful, it appends the resulting plaintext to dst and returns
// the updated slice.
//
// The ciphertext and dst may alias exactly or not at all. To reuse
// ciphertext's storage for the decrypted output, use ciphertext[:0] as dst.
//
// Even if the function fails, the contents of dst, up to its capacity,
// may be overwritten.
func (d *StreamDecryptor) Open(dst, ciphertext, aData []byte, lastBlock bool) ([]byte, error) {
return d.a.Open(dst, d.n.Next(lastBlock), ciphertext, aData)
}
// Computes STREAM nonces based on the current position in the STREAM.
//
// Accepts a 64-bit nonce and uses a 32-bit counter internally.
//
// Panics if the nonce size is incorrect, or the 32-bit counter overflows
type nonceEncoder32 struct {
value [streamExtendedNonceSize]byte
counter uint64
finished bool
}
func newNonceEncoder32(noncePrefix []byte) (*nonceEncoder32, error) {
if len(noncePrefix) != streamNoncePrefixSize {
panic("miscreant.STREAM: incorrect nonce length")
}
value := [streamExtendedNonceSize]byte{0}
copy(value[:streamNoncePrefixSize], noncePrefix)
return &nonceEncoder32{
value: value,
counter: 0,
finished: false,
}, nil
}
func (n *nonceEncoder32) Next(lastBlock bool) []byte {
if n.finished {
panic("miscreant.STREAM: already finished")
}
counterSlice := n.value[streamNoncePrefixSize : streamNoncePrefixSize+4]
binary.BigEndian.PutUint32(counterSlice, uint32(n.counter))
if lastBlock {
n.value[len(n.value)-1] = lastBlockFlag
n.finished = true
} else {
n.counter++
if n.counter > counterMax {
panic("miscreant.STREAM: nonce counter overflowed")
}
}
return n.value[:]
}