Skip to content
Permalink
Browse files

Use uint64 for all size calculations, size checks

  • Loading branch information...
csstaub committed Sep 3, 2016
1 parent d00415a commit 789a4c4bd4c118f7564954f441b29c153ccd6a96
Showing with 18 additions and 13 deletions.
  1. +8 −8 cipher/cbc_hmac.go
  2. +3 −3 cipher/cbc_hmac_test.go
  3. +1 −1 cipher/concat_kdf.go
  4. +6 −1 cipher/ecdh_es.go
@@ -82,7 +82,7 @@ func (ctx *cbcAEAD) Overhead() int {
// Seal encrypts and authenticates the plaintext.
func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
// Output buffer -- must take care not to mangle plaintext input.
ciphertext := make([]byte, len(plaintext)+ctx.Overhead())[:len(plaintext)]
ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)]
copy(ciphertext, plaintext)
ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize())

@@ -91,7 +91,7 @@ func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
cbc.CryptBlocks(ciphertext, ciphertext)
authtag := ctx.computeAuthTag(data, nonce, ciphertext)

ret, out := resize(dst, len(dst)+len(ciphertext)+len(authtag))
ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag)))
copy(out, ciphertext)
copy(out[len(ciphertext):], authtag)

@@ -128,20 +128,20 @@ func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
return nil, err
}

ret, out := resize(dst, len(dst)+len(plaintext))
ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext)))
copy(out, plaintext)

return ret, nil
}

// Compute an authentication tag
func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte {
buffer := make([]byte, len(aad)+len(nonce)+len(ciphertext)+8)
buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8)
n := 0
n += copy(buffer, aad)
n += copy(buffer[n:], nonce)
n += copy(buffer[n:], ciphertext)
binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad)*8))
binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8)

// According to documentation, Write() on hash.Hash never fails.
hmac := hmac.New(ctx.hash, ctx.integrityKey)
@@ -153,8 +153,8 @@ func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte {
// resize ensures the the given slice has a capacity of at least n bytes.
// If the capacity of the slice is less than n, a new slice is allocated
// and the existing data will be copied.
func resize(in []byte, n int) (head, tail []byte) {
if cap(in) >= n {
func resize(in []byte, n uint64) (head, tail []byte) {
if uint64(cap(in)) >= n {
head = in[:n]
} else {
head = make([]byte, n)
@@ -168,7 +168,7 @@ func resize(in []byte, n int) (head, tail []byte) {
// Apply padding
func padBuffer(buffer []byte, blockSize int) []byte {
missing := blockSize - (len(buffer) % blockSize)
ret, out := resize(buffer, len(buffer)+missing)
ret, out := resize(buffer, uint64(len(buffer))+uint64(missing))
padding := bytes.Repeat([]byte{byte(missing)}, missing)
copy(out, padding)
return ret
@@ -283,7 +283,7 @@ func TestTruncatedCiphertext(t *testing.T) {
ct := aead.Seal(nil, nonce, data, nil)

// Truncated ciphertext, but with correct auth tag
truncated, tail := resize(ct[:len(ct)-ctx.authtagBytes-2], len(ct)-2)
truncated, tail := resize(ct[:len(ct)-ctx.authtagBytes-2], uint64(len(ct))-2)
copy(tail, ctx.computeAuthTag(nil, nonce, truncated[:len(truncated)-ctx.authtagBytes]))

// Open should fail
@@ -313,8 +313,8 @@ func TestInvalidPaddingOpen(t *testing.T) {
ctx := aead.(*cbcAEAD)

// Mutated ciphertext, but with correct auth tag
size := len(buffer)
ciphertext, tail := resize(buffer, size+(len(key)/2))
size := uint64(len(buffer))
ciphertext, tail := resize(buffer, size+(uint64(len(key))/2))
copy(tail, ctx.computeAuthTag(nil, nonce, ciphertext[:size]))

// Open should fail (b/c of invalid padding, even though tag matches)
@@ -32,7 +32,7 @@ type concatKDF struct {

// NewConcatKDF builds a KDF reader based on the given inputs.
func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader {
buffer := make([]byte, len(algID)+len(ptyUInfo)+len(ptyVInfo)+len(supPubInfo)+len(supPrivInfo))
buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo)))
n := 0
n += copy(buffer, algID)
n += copy(buffer[n:], ptyUInfo)
@@ -24,8 +24,13 @@ import (

// DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA.
// It is an error to call this function with a private/public key that are not on the same
// curve. Callers must ensure that the keys are valid before calling this function.
// curve. Callers must ensure that the keys are valid before calling this function. Output
// size may be at most 1<<16 bytes (64 KiB).
func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte {
if size > 1<<16 {
panic("ECDH-ES output size too large, must be less than 1<<16")

This comment has been minimized.

Copy link
@RalphCorderoy

RalphCorderoy Jul 20, 2018

The error message is wrong. The output size must be no more than 1<<16.

}

// algId, partyUInfo, partyVInfo inputs must be prefixed with the length
algID := lengthPrefixed([]byte(alg))
ptyUInfo := lengthPrefixed(apuData)

0 comments on commit 789a4c4

Please sign in to comment.
You can’t perform that action at this time.