e827763f2e
This fixes a few issues I have found reviewing the code: 1) Limit the amount of data ReadLongName() will read. Previously, you could send gocryptfs into out-of-memory by symlinking gocryptfs.diriv to /dev/zero. 2) Handle the empty input case in unPad16() by returning an error. Previously, it would panic with an out-of-bounds array read. It is unclear to me if this could actually be triggered. 3) Reject empty names after base64-decoding in DecryptName(). An empty name crashes emeCipher.Decrypt(). It is unclear to me if B64.DecodeString() can actually return a non-error empty result, but let's guard against it anyway.
65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package nametransform
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
)
|
|
|
|
// pad16 - pad data to AES block size (=16 byte) using standard PKCS#7 padding
|
|
// https://tools.ietf.org/html/rfc5652#section-6.3
|
|
func pad16(orig []byte) (padded []byte) {
|
|
oldLen := len(orig)
|
|
if oldLen == 0 {
|
|
log.Panic("Padding zero-length string makes no sense")
|
|
}
|
|
padLen := aes.BlockSize - oldLen%aes.BlockSize
|
|
if padLen == 0 {
|
|
padLen = aes.BlockSize
|
|
}
|
|
newLen := oldLen + padLen
|
|
padded = make([]byte, newLen)
|
|
copy(padded, orig)
|
|
padByte := byte(padLen)
|
|
for i := oldLen; i < newLen; i++ {
|
|
padded[i] = padByte
|
|
}
|
|
return padded
|
|
}
|
|
|
|
// unPad16 - remove padding
|
|
func unPad16(padded []byte) ([]byte, error) {
|
|
oldLen := len(padded)
|
|
if oldLen == 0 {
|
|
return nil, errors.New("Empty input")
|
|
}
|
|
if oldLen%aes.BlockSize != 0 {
|
|
return nil, errors.New("Unaligned size")
|
|
}
|
|
// The last byte is always a padding byte
|
|
padByte := padded[oldLen-1]
|
|
// The padding byte's value is the padding length
|
|
padLen := int(padByte)
|
|
// Padding must be at least 1 byte
|
|
if padLen == 0 {
|
|
return nil, errors.New("Padding cannot be zero-length")
|
|
}
|
|
// Padding more than 16 bytes make no sense
|
|
if padLen > aes.BlockSize {
|
|
return nil, fmt.Errorf("Padding too long, padLen=%d > 16", padLen)
|
|
}
|
|
// Padding cannot be as long as (or longer than) the whole string,
|
|
if padLen >= oldLen {
|
|
return nil, fmt.Errorf("Padding too long, oldLen=%d >= padLen=%d", oldLen, padLen)
|
|
}
|
|
// All padding bytes must be identical
|
|
for i := oldLen - padLen; i < oldLen; i++ {
|
|
if padded[i] != padByte {
|
|
return nil, fmt.Errorf("Padding byte at i=%d is invalid", i)
|
|
}
|
|
}
|
|
newLen := oldLen - padLen
|
|
return padded[0:newLen], nil
|
|
}
|