mirror of
https://github.com/golang/go
synced 2024-11-20 03:04:40 -07:00
crypto/x509: fix DecryptPEMBlock
The current implement can fail when the block size is not a multiple of 8 bytes. This CL makes it work, and also checks that the data is in fact a multiple of the block size. R=agl, agl CC=golang-dev https://golang.org/cl/6827058
This commit is contained in:
parent
cb856adea9
commit
768ba46cc1
@ -25,6 +25,16 @@ type rfc1423Algo struct {
|
||||
keySize int
|
||||
}
|
||||
|
||||
// rfc1423Algos is a mapping of encryption algorithm to an rfc1423Algo that can
|
||||
// create block ciphers for that mode.
|
||||
var rfc1423Algos = map[string]rfc1423Algo{
|
||||
"DES-CBC": {des.NewCipher, 8},
|
||||
"DES-EDE3-CBC": {des.NewTripleDESCipher, 24},
|
||||
"AES-128-CBC": {aes.NewCipher, 16},
|
||||
"AES-192-CBC": {aes.NewCipher, 24},
|
||||
"AES-256-CBC": {aes.NewCipher, 32},
|
||||
}
|
||||
|
||||
// deriveKey uses a key derivation function to stretch the password into a key
|
||||
// with the number of bits our cipher requires. This algorithm was derived from
|
||||
// the OpenSSL source.
|
||||
@ -45,16 +55,6 @@ func (c rfc1423Algo) deriveKey(password, salt []byte) []byte {
|
||||
return out
|
||||
}
|
||||
|
||||
// rfc1423Algos is a mapping of encryption algorithm to an rfc1423Algo that can
|
||||
// create block ciphers for that mode.
|
||||
var rfc1423Algos = map[string]rfc1423Algo{
|
||||
"DES-CBC": {des.NewCipher, 8},
|
||||
"DES-EDE3-CBC": {des.NewTripleDESCipher, 24},
|
||||
"AES-128-CBC": {aes.NewCipher, 16},
|
||||
"AES-192-CBC": {aes.NewCipher, 24},
|
||||
"AES-256-CBC": {aes.NewCipher, 32},
|
||||
}
|
||||
|
||||
// IsEncryptedPEMBlock returns if the PEM block is password encrypted.
|
||||
func IsEncryptedPEMBlock(b *pem.Block) bool {
|
||||
_, ok := b.Headers["DEK-Info"]
|
||||
@ -81,6 +81,10 @@ func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
mode, hexIV := dek[:idx], dek[idx+1:]
|
||||
ciph, ok := rfc1423Algos[mode]
|
||||
if !ok {
|
||||
return nil, errors.New("x509: unknown encryption mode")
|
||||
}
|
||||
iv, err := hex.DecodeString(hexIV)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -89,11 +93,6 @@ func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
|
||||
return nil, errors.New("x509: not enough bytes in IV")
|
||||
}
|
||||
|
||||
ciph, ok := rfc1423Algos[mode]
|
||||
if !ok {
|
||||
return nil, errors.New("x509: unknown encryption mode")
|
||||
}
|
||||
|
||||
// Based on the OpenSSL implementation. The salt is the first 8 bytes
|
||||
// of the initialization vector.
|
||||
key := ciph.deriveKey(password, iv[:8])
|
||||
@ -107,27 +106,27 @@ func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
|
||||
dec.CryptBlocks(data, b.Bytes)
|
||||
|
||||
// Blocks are padded using a scheme where the last n bytes of padding are all
|
||||
// equal to n. It can pad from 1 to 8 bytes inclusive. See RFC 1423.
|
||||
// equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423.
|
||||
// For example:
|
||||
// [x y z 2 2]
|
||||
// [x y 7 7 7 7 7 7 7]
|
||||
// If we detect a bad padding, we assume it is an invalid password.
|
||||
dlen := len(data)
|
||||
if dlen == 0 {
|
||||
blockSize := block.BlockSize()
|
||||
if dlen == 0 || dlen%blockSize != 0 {
|
||||
return nil, errors.New("x509: invalid padding")
|
||||
}
|
||||
last := data[dlen-1]
|
||||
if dlen < int(last) {
|
||||
last := int(data[dlen-1])
|
||||
if dlen < last {
|
||||
return nil, IncorrectPasswordError
|
||||
}
|
||||
if last == 0 || last > 8 {
|
||||
if last == 0 || last > blockSize {
|
||||
return nil, IncorrectPasswordError
|
||||
}
|
||||
for _, val := range data[dlen-int(last):] {
|
||||
if val != last {
|
||||
for _, val := range data[dlen-last:] {
|
||||
if int(val) != last {
|
||||
return nil, IncorrectPasswordError
|
||||
}
|
||||
}
|
||||
|
||||
return data[:dlen-int(last)], nil
|
||||
return data[:dlen-last], nil
|
||||
}
|
||||
|
@ -114,6 +114,21 @@ Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/
|
||||
2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N
|
||||
sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk
|
||||
clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0=
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
},
|
||||
{
|
||||
// generated with:
|
||||
// openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128
|
||||
kind: "AES-128-CBC",
|
||||
password: []byte("asdf"),
|
||||
pemData: []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
|
||||
|
||||
6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3
|
||||
eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD
|
||||
hTP8O1mS/MHl92NE0nhv0w==
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user