From 3eabc63e630f7e0a5252c69d9bddf9b0d8338088 Mon Sep 17 00:00:00 2001 From: Alex Zorin Date: Tue, 30 Jul 2019 19:15:11 +1000 Subject: [PATCH] decryption: perform sanity checking on padding Fixes the panic reported in #2 --- crypto.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/crypto.go b/crypto.go index 24a5548..dcd3fc3 100644 --- a/crypto.go +++ b/crypto.go @@ -10,6 +10,7 @@ import ( "encoding/base64" "encoding/binary" "encoding/hex" + "errors" "fmt" "io" "math" @@ -106,10 +107,23 @@ func decryptToken(encryptedSeedB64, salt, passphrase string) (string, error) { // The padding scheme seems to me that the final block will be padded with // the length of the padding. In the case when the plaintext aligns with // the block size, the final block will be padding-only. - paddingLen := int(out[len(out)-1]) - out = out[:len(out)-paddingLen] + // Additionally, since CBC is not authenticated, we need to ensure that the + // padding is not just garbage bytes. + paddingLen := out[len(out)-1] + paddingStart := len(out) - int(paddingLen) - return hex.EncodeToString(out), nil + if paddingLen > aes.BlockSize || paddingStart >= len(out) { + return "", errors.New("decryption failed") + } + cmp := true + for _, pad := range out[paddingStart:] { + cmp = cmp && pad == paddingLen + } + if !cmp { + return "", errors.New("decryption failed") + } + + return hex.EncodeToString(out[:paddingStart]), nil } func randomBytes(byteSize int) ([]byte, error) {