From 7371cede0641b7e2ab5f5314140b14eee21ab8a0 Mon Sep 17 00:00:00 2001 From: thaidn Date: Thu, 15 Oct 2020 11:20:16 -0700 Subject: [PATCH] Add size checks. PiperOrigin-RevId: 337347087 --- go/aead/aead_factory.go | 6 +----- go/aead/subtle/aead.go | 4 ++++ go/aead/subtle/aes_ctr.go | 3 +++ go/aead/subtle/aes_gcm.go | 20 +++++++++++++------- go/aead/subtle/chacha20poly1305.go | 16 ++++++++++++---- go/aead/subtle/xchacha20poly1305.go | 12 ++++++++---- go/daead/daead_factory.go | 6 +----- go/daead/subtle/aes_siv.go | 10 ++++++++-- go/hybrid/hybrid_encrypt_factory.go | 7 +------ go/mac/mac_factory.go | 5 +---- go/signature/signer_factory.go | 6 +----- 11 files changed, 53 insertions(+), 42 deletions(-) diff --git a/go/aead/aead_factory.go b/go/aead/aead_factory.go index b5efd117c7..2c28bdd3bc 100644 --- a/go/aead/aead_factory.go +++ b/go/aead/aead_factory.go @@ -77,11 +77,7 @@ func (a *wrappedAead) Encrypt(pt, ad []byte) ([]byte, error) { if err != nil { return nil, err } - ret := make([]byte, 0, len(primary.Prefix)+len(ct)) - ret = append(ret, primary.Prefix...) - ret = append(ret, ct...) - - return ret, nil + return append([]byte(primary.Prefix), ct...), nil } // Decrypt decrypts the given ciphertext and authenticates it with the given diff --git a/go/aead/subtle/aead.go b/go/aead/subtle/aead.go index 551e5da2a2..8a5053cbd9 100644 --- a/go/aead/subtle/aead.go +++ b/go/aead/subtle/aead.go @@ -17,6 +17,10 @@ package subtle import "fmt" +const ( + maxInt = int(^uint(0) >> 1) +) + // ValidateAESKeySize checks if the given key size is a valid AES key size. func ValidateAESKeySize(sizeInBytes uint32) error { switch sizeInBytes { diff --git a/go/aead/subtle/aes_ctr.go b/go/aead/subtle/aes_ctr.go index 72c08ee7cf..1b802918df 100644 --- a/go/aead/subtle/aes_ctr.go +++ b/go/aead/subtle/aes_ctr.go @@ -52,6 +52,9 @@ func NewAESCTR(key []byte, ivSize int) (*AESCTR, error) { // The resulting ciphertext consists of two parts: // (1) the IV used for encryption and (2) the actual ciphertext. func (a *AESCTR) Encrypt(plaintext []byte) ([]byte, error) { + if len(plaintext) > maxInt-a.IVSize { + return nil, fmt.Errorf("aes_ctr: plaintext too long") + } iv := a.newIV() stream, err := newCipher(a.Key, iv) if err != nil { diff --git a/go/aead/subtle/aes_gcm.go b/go/aead/subtle/aes_gcm.go index 56d46f106f..22d3969dfa 100644 --- a/go/aead/subtle/aes_gcm.go +++ b/go/aead/subtle/aes_gcm.go @@ -27,7 +27,8 @@ const ( // AESGCMIVSize is the only IV size that this implementation supports. AESGCMIVSize = 12 // AESGCMTagSize is the only tag size that this implementation supports. - AESGCMTagSize = 16 + AESGCMTagSize = 16 + maxAESGCMPlaintextSize = (1 << 36) - 32 ) // AESGCM is an implementation of AEAD interface. @@ -58,7 +59,7 @@ func NewAESGCM(key []byte) (*AESGCM, error) { func (a *AESGCM) Encrypt(pt, aad []byte) ([]byte, error) { // Although Seal() function already checks for plaintext length, // this check is repeated here to avoid panic. - if uint64(len(pt)) > (1<<36)-32 { + if len(pt) > maxPtSize() { return nil, fmt.Errorf("aes_gcm: plaintext too long") } cipher, err := a.newCipher(a.Key) @@ -67,13 +68,10 @@ func (a *AESGCM) Encrypt(pt, aad []byte) ([]byte, error) { } iv := a.newIV() ct := cipher.Seal(nil, iv, pt, aad) - ret := make([]byte, 0, len(iv)+len(ct)) - ret = append(ret, iv...) - ret = append(ret, ct...) - return ret, nil + return append(iv, ct...), nil } -// Decrypt decrypts ct with aad as the additionalauthenticated data. +// Decrypt decrypts ct with aad as the additional authenticated data. func (a *AESGCM) Decrypt(ct, aad []byte) ([]byte, error) { if len(ct) < AESGCMIVSize+AESGCMTagSize { return nil, fmt.Errorf("aes_gcm: ciphertext too short") @@ -109,3 +107,11 @@ func (a *AESGCM) newCipher(key []byte) (cipher.AEAD, error) { } return ret, nil } + +func maxPtSize() int { + x := maxInt - AESGCMIVSize - AESGCMTagSize + if x > maxAESGCMPlaintextSize { + return maxAESGCMPlaintextSize + } + return x +} diff --git a/go/aead/subtle/chacha20poly1305.go b/go/aead/subtle/chacha20poly1305.go index bfa01ce118..c595f85211 100644 --- a/go/aead/subtle/chacha20poly1305.go +++ b/go/aead/subtle/chacha20poly1305.go @@ -23,6 +23,10 @@ import ( "github.com/google/tink/go/tink" ) +const ( + poly1305TagSize = 16 +) + // ChaCha20Poly1305 is an implementation of AEAD interface. type ChaCha20Poly1305 struct { Key []byte @@ -45,6 +49,9 @@ func NewChaCha20Poly1305(key []byte) (*ChaCha20Poly1305, error) { // authenticated data. The resulting ciphertext consists of two parts: // (1) the nonce used for encryption and (2) the actual ciphertext. func (ca *ChaCha20Poly1305) Encrypt(pt []byte, aad []byte) ([]byte, error) { + if len(pt) > maxInt-chacha20poly1305.NonceSize-poly1305TagSize { + return nil, fmt.Errorf("chacha20poly1305: plaintext too long") + } c, err := chacha20poly1305.New(ca.Key) if err != nil { return nil, err @@ -52,14 +59,15 @@ func (ca *ChaCha20Poly1305) Encrypt(pt []byte, aad []byte) ([]byte, error) { n := ca.newNonce() ct := c.Seal(nil, n, pt, aad) - ret := make([]byte, 0, len(n)+len(ct)) - ret = append(ret, n...) - ret = append(ret, ct...) - return ret, nil + return append(n, ct...), nil } // Decrypt decrypts {@code ct} with {@code aad} as the additionalauthenticated data. func (ca *ChaCha20Poly1305) Decrypt(ct []byte, aad []byte) ([]byte, error) { + if len(ct) < chacha20poly1305.NonceSize+poly1305TagSize { + return nil, fmt.Errorf("chacha20poly1305: ciphertext too short") + } + c, err := chacha20poly1305.New(ca.Key) if err != nil { return nil, err diff --git a/go/aead/subtle/xchacha20poly1305.go b/go/aead/subtle/xchacha20poly1305.go index d178cb0748..ecc2e4f67a 100644 --- a/go/aead/subtle/xchacha20poly1305.go +++ b/go/aead/subtle/xchacha20poly1305.go @@ -45,6 +45,9 @@ func NewXChaCha20Poly1305(key []byte) (*XChaCha20Poly1305, error) { // authenticated data. The resulting ciphertext consists of two parts: // (1) the nonce used for encryption and (2) the actual ciphertext. func (x *XChaCha20Poly1305) Encrypt(pt []byte, aad []byte) ([]byte, error) { + if len(pt) > maxInt-chacha20poly1305.NonceSizeX-poly1305TagSize { + return nil, fmt.Errorf("xchacha20poly1305: plaintext too long") + } c, err := chacha20poly1305.NewX(x.Key) if err != nil { return nil, err @@ -52,14 +55,15 @@ func (x *XChaCha20Poly1305) Encrypt(pt []byte, aad []byte) ([]byte, error) { n := x.newNonce() ct := c.Seal(nil, n, pt, aad) - var ret []byte - ret = append(ret, n...) - ret = append(ret, ct...) - return ret, nil + return append(n, ct...), nil } // Decrypt decrypts {@code ct} with {@code aad} as the additionalauthenticated data. func (x *XChaCha20Poly1305) Decrypt(ct []byte, aad []byte) ([]byte, error) { + if len(ct) < chacha20poly1305.NonceSizeX+poly1305TagSize { + return nil, fmt.Errorf("xchacha20poly1305: ciphertext too short") + } + c, err := chacha20poly1305.NewX(x.Key) if err != nil { return nil, err diff --git a/go/daead/daead_factory.go b/go/daead/daead_factory.go index ae499a77dc..b2b6c8cac8 100644 --- a/go/daead/daead_factory.go +++ b/go/daead/daead_factory.go @@ -75,11 +75,7 @@ func (d *wrappedDeterministicAEAD) EncryptDeterministically(pt, aad []byte) ([]b if err != nil { return nil, err } - - ret := make([]byte, 0, len(primary.Prefix)+len(ct)) - ret = append(ret, primary.Prefix...) - ret = append(ret, ct...) - return ret, nil + return append([]byte(primary.Prefix), ct...), nil } // DecryptDeterministically deterministically decrypts ciphertext with additionalData as diff --git a/go/daead/subtle/aes_siv.go b/go/daead/subtle/aes_siv.go index cf38801cea..f37e147a0d 100644 --- a/go/daead/subtle/aes_siv.go +++ b/go/daead/subtle/aes_siv.go @@ -56,8 +56,11 @@ type AESSIV struct { Cipher cipher.Block } -// AESSIVKeySize is the key size in bytes. -const AESSIVKeySize = 64 +const ( + // AESSIVKeySize is the key size in bytes. + AESSIVKeySize = 64 + maxInt = int(^uint(0) >> 1) +) // NewAESSIV returns an AESSIV instance. func NewAESSIV(key []byte) (*AESSIV, error) { @@ -105,6 +108,9 @@ func multiplyByX(block []byte) { // EncryptDeterministically deterministically encrypts plaintext with // additionalData as additional authenticated data. func (asc *AESSIV) EncryptDeterministically(pt, aad []byte) ([]byte, error) { + if len(pt) > maxInt-aes.BlockSize { + return nil, fmt.Errorf("aes_siv: plaintext too long") + } siv := make([]byte, aes.BlockSize) asc.s2v(pt, aad, siv) diff --git a/go/hybrid/hybrid_encrypt_factory.go b/go/hybrid/hybrid_encrypt_factory.go index f2facaefb2..146cbb0a06 100644 --- a/go/hybrid/hybrid_encrypt_factory.go +++ b/go/hybrid/hybrid_encrypt_factory.go @@ -75,10 +75,5 @@ func (a *wrappedHybridEncrypt) Encrypt(pt, ad []byte) ([]byte, error) { if err != nil { return nil, err } - - ret := make([]byte, 0, len(primary.Prefix)+len(ct)) - ret = append(ret, primary.Prefix...) - ret = append(ret, ct...) - - return ret, nil + return append([]byte(primary.Prefix), ct...), nil } diff --git a/go/mac/mac_factory.go b/go/mac/mac_factory.go index cc53784dda..d7856df665 100644 --- a/go/mac/mac_factory.go +++ b/go/mac/mac_factory.go @@ -89,10 +89,7 @@ func (m *wrappedMAC) ComputeMAC(data []byte) ([]byte, error) { if err != nil { return nil, err } - ret := make([]byte, 0, len(primary.Prefix)+len(mac)) - ret = append(ret, primary.Prefix...) - ret = append(ret, mac...) - return ret, nil + return append([]byte(primary.Prefix), mac...), nil } var errInvalidMAC = fmt.Errorf("mac_factory: invalid mac") diff --git a/go/signature/signer_factory.go b/go/signature/signer_factory.go index 810140bdf8..14029690a5 100644 --- a/go/signature/signer_factory.go +++ b/go/signature/signer_factory.go @@ -88,9 +88,5 @@ func (s *wrappedSigner) Sign(data []byte) ([]byte, error) { if err != nil { return nil, err } - - ret := make([]byte, 0, len(primary.Prefix)+len(signature)) - ret = append(ret, primary.Prefix...) - ret = append(ret, signature...) - return ret, nil + return append([]byte(primary.Prefix), signature...), nil }