Repository navigation
Expand file tree
/
Copy pathdecrypt_security_test.go
More file actions
112 lines (109 loc) · 3.74 KB
/
Copy pathdecrypt_security_test.go
File metadata and controls
112 lines (109 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package pkcs7
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/x509/pkix"
"encoding/asn1"
"fmt"
"testing"
)
func TestUnpadSecurity(t *testing.T) {
for _, size := range []int{8, 16} {
for padlen := 0; padlen < 256; padlen++ {
data := bytes.Repeat([]byte{byte(padlen)}, size*2)
got, err := unpad(data, size)
valid := padlen >= 1 && padlen <= size
if valid && (err != nil || !bytes.Equal(got, data[:len(data)-padlen])) {
t.Fatalf("size=%d pad=%d: %x, %v", size, padlen, got, err)
}
if !valid && (err == nil || got != nil) {
t.Fatalf("accepted size=%d pad=%d", size, padlen)
}
}
for pos := 0; pos < size; pos++ {
data := bytes.Repeat([]byte{byte(size)}, size)
data[pos] ^= 1
if got, err := unpad(data, size); err == nil || got != nil {
t.Fatalf("accepted corrupt padding at %d", pos)
}
}
}
for _, tc := range []struct {
data []byte
size int
}{{nil, 8}, {[]byte{1}, 8}, {[]byte{1}, 0}, {[]byte{1}, -1}} {
if got, err := unpad(tc.data, tc.size); err == nil || got != nil {
t.Fatal("accepted malformed input")
}
}
}
func TestCBCPaddingSecurity(t *testing.T) {
algorithms := []struct {
name string
oid asn1.ObjectIdentifier
key []byte
block cipher.Block
}{
{name: "DES", oid: OIDEncryptionAlgorithmDESCBC, key: make([]byte, 8)},
{name: "3DES", oid: OIDEncryptionAlgorithmDESEDE3CBC, key: make([]byte, 24)},
{name: "AES128", oid: OIDEncryptionAlgorithmAES128CBC, key: make([]byte, 16)},
{name: "AES256", oid: OIDEncryptionAlgorithmAES256CBC, key: make([]byte, 32)},
}
for _, alg := range algorithms {
var err error
switch alg.name {
case "DES":
alg.block, err = des.NewCipher(alg.key)
case "3DES":
alg.block, err = des.NewTripleDESCipher(alg.key)
default:
alg.block, err = aes.NewCipher(alg.key)
}
if err != nil {
t.Fatal(err)
}
size := alg.block.BlockSize()
for _, compound := range []bool{false, true} {
t.Run(fmt.Sprintf("%s/constructed=%v", alg.name, compound), func(t *testing.T) {
for padlen := 0; padlen < 256; padlen++ {
plain := bytes.Repeat([]byte{byte(padlen)}, size)
ciphertext := make([]byte, size)
// #nosec G407 -- A fixed IV is intentional for synthetic padding-validation fixtures.
cipher.NewCBCEncrypter(alg.block, make([]byte, size)).CryptBlocks(ciphertext, plain)
eci := encryptedContentInfo{ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: alg.oid, Parameters: asn1.RawValue{Bytes: make([]byte, size)}}, EncryptedContent: asn1.RawValue{Bytes: ciphertext}}
if compound {
encoded, e := asn1.Marshal(ciphertext)
if e != nil {
t.Fatal(e)
}
eci.EncryptedContent = asn1.RawValue{IsCompound: true, Bytes: encoded}
}
p7 := PKCS7{raw: encryptedData{EncryptedContentInfo: eci}}
got, e := p7.DecryptUsingPSK(alg.key)
valid := padlen >= 1 && padlen <= size
if valid && (e != nil || !bytes.Equal(got, plain[:size-padlen])) {
t.Fatalf("pad=%d: %x, %v", padlen, got, e)
}
if !valid && (e == nil || got != nil || e.Error() != "invalid padding") {
t.Fatalf("pad=%d: %x, %v", padlen, got, e)
}
}
for _, length := range []int{0, 1, size - 1, size + 1} {
eci := encryptedContentInfo{ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: alg.oid, Parameters: asn1.RawValue{Bytes: make([]byte, size)}}, EncryptedContent: asn1.RawValue{Bytes: make([]byte, length)}}
if compound {
encoded, e := asn1.Marshal(eci.EncryptedContent.Bytes)
if e != nil {
t.Fatal(e)
}
eci.EncryptedContent = asn1.RawValue{IsCompound: true, Bytes: encoded}
}
if got, e := eci.decrypt(alg.key); e == nil || got != nil {
t.Fatalf("accepted ciphertext length %d", length)
}
}
})
}
}
}