Add error handling for encryption routines
This commit is contained in:
parent
6ac5754075
commit
f798ef3825
|
@ -9,6 +9,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
@ -170,7 +171,7 @@ func isMacValid(message, messageMAC, key []byte) bool {
|
||||||
return hmac.Equal(messageMAC, expectedMAC)
|
return hmac.Equal(messageMAC, expectedMAC)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encryptAESCBC256(data, key []byte) (iv, ciphertext []byte, _ error) {
|
func encryptAESCBC256(data, key []byte) (iv, ciphertext []byte, err error) {
|
||||||
data = padPKCS7(data, aes.BlockSize)
|
data = padPKCS7(data, aes.BlockSize)
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -182,12 +183,28 @@ func encryptAESCBC256(data, key []byte) (iv, ciphertext []byte, _ error) {
|
||||||
if _, err := io.ReadFull(cryptorand.Reader, iv); err != nil {
|
if _, err := io.ReadFull(cryptorand.Reader, iv); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
var ok bool
|
||||||
|
err, ok = r.(error)
|
||||||
|
if !ok {
|
||||||
|
iv = nil
|
||||||
|
ciphertext = nil
|
||||||
|
err = errors.New("error encrypting AES CBC 256 data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
mode := cipher.NewCBCEncrypter(block, iv)
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||||||
mode.CryptBlocks(ciphertext, data)
|
mode.CryptBlocks(ciphertext, data)
|
||||||
return iv, ciphertext, nil
|
return iv, ciphertext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decryptAESCBC256(iv, ciphertext, key []byte) ([]byte, error) {
|
func decryptAESCBC256(iv, ciphertext, key []byte) (decryptedData []byte, err error) {
|
||||||
|
ciphertextCopy := make([]byte, len(ciphertext))
|
||||||
|
copy(ciphertextCopy, ciphertext)
|
||||||
|
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -195,28 +212,50 @@ func decryptAESCBC256(iv, ciphertext, key []byte) ([]byte, error) {
|
||||||
if len(iv) != aes.BlockSize {
|
if len(iv) != aes.BlockSize {
|
||||||
return nil, fmt.Errorf("iv length does not match AES block size")
|
return nil, fmt.Errorf("iv length does not match AES block size")
|
||||||
}
|
}
|
||||||
if len(ciphertext)%aes.BlockSize != 0 {
|
if len(ciphertextCopy)%aes.BlockSize != 0 {
|
||||||
return nil, fmt.Errorf("ciphertext is not a multiple of AES block size")
|
return nil, fmt.Errorf("ciphertext is not a multiple of AES block size")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
var ok bool
|
||||||
|
err, ok = r.(error)
|
||||||
|
if !ok {
|
||||||
|
decryptedData = nil
|
||||||
|
err = errors.New("error decrypting AES CBC 256 data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
mode := cipher.NewCBCDecrypter(block, iv)
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||||||
mode.CryptBlocks(ciphertext, ciphertext) // decrypt in-place
|
mode.CryptBlocks(ciphertextCopy, ciphertextCopy) // decrypt in-place
|
||||||
data, err := unpadPKCS7(ciphertext, aes.BlockSize)
|
data, err := unpadPKCS7(ciphertextCopy, aes.BlockSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return data, nil
|
|
||||||
|
resultBuffer := make([]byte, len(data))
|
||||||
|
copy(resultBuffer, data)
|
||||||
|
return resultBuffer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unpadPKCS7(src []byte, size int) ([]byte, error) {
|
func unpadPKCS7(src []byte, size int) ([]byte, error) {
|
||||||
n := src[len(src)-1]
|
srcCopy := make([]byte, len(src))
|
||||||
if len(src)%size != 0 {
|
copy(srcCopy, src)
|
||||||
return nil, fmt.Errorf("expected PKCS7 padding for block size %d, but have %d bytes", size, len(src))
|
|
||||||
|
n := srcCopy[len(srcCopy)-1]
|
||||||
|
if len(srcCopy)%size != 0 {
|
||||||
|
return nil, fmt.Errorf("expected PKCS7 padding for block size %d, but have %d bytes", size, len(srcCopy))
|
||||||
}
|
}
|
||||||
if len(src) <= int(n) {
|
if len(srcCopy) <= int(n) {
|
||||||
return nil, fmt.Errorf("cannot unpad %d bytes out of a total of %d", n, len(src))
|
return nil, fmt.Errorf("cannot unpad %d bytes out of a total of %d", n, len(srcCopy))
|
||||||
}
|
}
|
||||||
src = src[:len(src)-int(n)]
|
srcCopy = srcCopy[:len(srcCopy)-int(n)]
|
||||||
return src, nil
|
|
||||||
|
resultCopy := make([]byte, len(srcCopy))
|
||||||
|
copy(resultCopy, srcCopy)
|
||||||
|
|
||||||
|
return resultCopy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func padPKCS7(src []byte, size int) []byte {
|
func padPKCS7(src []byte, size int) []byte {
|
||||||
|
|
|
@ -2,8 +2,6 @@ package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
@ -12,12 +10,14 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/awnumar/memguard"
|
"github.com/awnumar/memguard"
|
||||||
|
"github.com/quexten/goldwarden/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var cryptoLog = logging.GetLogger("Goldwarden", "Crypto")
|
||||||
|
|
||||||
type EncString struct {
|
type EncString struct {
|
||||||
Type EncStringType
|
Type EncStringType
|
||||||
IV, CT, MAC []byte
|
IV, CT, MAC []byte
|
||||||
|
@ -131,11 +131,6 @@ func DecryptWith(s EncString, key SymmetricEncryptionKey) ([]byte, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := aes.NewCipher(encKeyData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s.Type {
|
switch s.Type {
|
||||||
case AesCbc256_B64, AesCbc256_HmacSha256_B64:
|
case AesCbc256_B64, AesCbc256_HmacSha256_B64:
|
||||||
break
|
break
|
||||||
|
@ -161,13 +156,11 @@ func DecryptWith(s EncString, key SymmetricEncryptionKey) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("decrypt: invalid IV length, expected %d, got %d", block.BlockSize(), len(s.IV))
|
return nil, fmt.Errorf("decrypt: invalid IV length, expected %d, got %d", block.BlockSize(), len(s.IV))
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := cipher.NewCBCDecrypter(block, s.IV)
|
dst, err := decryptAESCBC256(s.IV, s.CT, encKeyData)
|
||||||
dst := make([]byte, len(s.CT))
|
|
||||||
mode.CryptBlocks(dst, s.CT)
|
|
||||||
dst, err = unpadPKCS7(dst, aes.BlockSize)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst, nil
|
return dst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,19 +181,13 @@ func EncryptWith(data []byte, encType EncStringType, key SymmetricEncryptionKey)
|
||||||
return s, fmt.Errorf("encrypt: unsupported cipher type %q", s.Type)
|
return s, fmt.Errorf("encrypt: unsupported cipher type %q", s.Type)
|
||||||
}
|
}
|
||||||
s.Type = encType
|
s.Type = encType
|
||||||
data = padPKCS7(data, aes.BlockSize)
|
|
||||||
|
|
||||||
block, err := aes.NewCipher(encKeyData)
|
iv, ciphertext, err := encryptAESCBC256(data, encKeyData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
s.IV = make([]byte, aes.BlockSize)
|
s.CT = ciphertext
|
||||||
if _, err := io.ReadFull(rand.Reader, s.IV); err != nil {
|
s.IV = iv
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
s.CT = make([]byte, len(data))
|
|
||||||
mode := cipher.NewCBCEncrypter(block, s.IV)
|
|
||||||
mode.CryptBlocks(s.CT, data)
|
|
||||||
|
|
||||||
if encType == AesCbc256_HmacSha256_B64 {
|
if encType == AesCbc256_HmacSha256_B64 {
|
||||||
if len(macKeyData) == 0 {
|
if len(macKeyData) == 0 {
|
||||||
|
|
Loading…
Reference in New Issue