1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package pkcs7
18
19 import (
20 "bytes"
21 "crypto/hmac"
22 "crypto/rsa"
23 "crypto/x509"
24 "fmt"
25 "time"
26
27 "github.com/pkg/errors"
28 "github.com/sassoftware/relic/lib/x509tools"
29 )
30
31 type Signature struct {
32 SignerInfo *SignerInfo
33 Certificate *x509.Certificate
34 Intermediates []*x509.Certificate
35 }
36
37
38
39
40
41
42
43
44 func (sd *SignedData) Verify(externalContent []byte, skipDigests bool) (Signature, error) {
45 var content []byte
46 if !skipDigests {
47 var err error
48 content, err = sd.ContentInfo.Bytes()
49 if err != nil {
50 return Signature{}, err
51 } else if content == nil {
52 if externalContent == nil {
53 return Signature{}, errors.New("pkcs7: missing content")
54 }
55 content = externalContent
56 } else if externalContent != nil {
57 if !bytes.Equal(externalContent, content) {
58 return Signature{}, errors.New("pkcs7: internal and external content were both provided but are not equal")
59 }
60 }
61 }
62 certs, err := sd.Certificates.Parse()
63 if err != nil {
64 return Signature{}, fmt.Errorf("pkcs7: %s", err)
65 } else if len(certs) == 0 {
66 return Signature{}, errors.New("pkcs7: certificate missing from signedData")
67 }
68 var cert *x509.Certificate
69 var sig Signature
70 for _, si := range sd.SignerInfos {
71 cert, err = si.Verify(content, skipDigests, certs)
72 if err != nil {
73 return Signature{}, err
74 }
75 sig = Signature{&si, cert, certs}
76 }
77 return sig, nil
78 }
79
80
81 func (si *SignerInfo) FindCertificate(certs []*x509.Certificate) (*x509.Certificate, error) {
82 is := si.IssuerAndSerialNumber
83 for _, cert := range certs {
84 if bytes.Equal(cert.RawIssuer, is.IssuerName.FullBytes) && cert.SerialNumber.Cmp(is.SerialNumber) == 0 {
85 return cert, nil
86 }
87 }
88 return nil, errors.New("pkcs7: certificate missing from signedData")
89 }
90
91
92
93 func (si *SignerInfo) Verify(content []byte, skipDigests bool, certs []*x509.Certificate) (*x509.Certificate, error) {
94 hash, err := x509tools.PkixDigestToHashE(si.DigestAlgorithm)
95 if err != nil {
96 return nil, errors.Wrap(err, "pkcs7")
97 }
98 var digest []byte
99 if !skipDigests {
100 w := hash.New()
101 w.Write(content)
102 digest = w.Sum(nil)
103 }
104 if len(si.AuthenticatedAttributes) != 0 {
105
106 var md []byte
107 if err := si.AuthenticatedAttributes.GetOne(OidAttributeMessageDigest, &md); err != nil {
108 return nil, err
109 } else if digest != nil && !hmac.Equal(md, digest) {
110 return nil, errors.New("pkcs7: content digest does not match")
111 }
112
113 w := hash.New()
114 attrbytes, err := si.AuthenticatedAttributes.Bytes()
115 if err != nil {
116 return nil, err
117 }
118 w.Write(attrbytes)
119 digest = w.Sum(nil)
120 }
121 cert, err := si.FindCertificate(certs)
122 if err != nil {
123 return nil, err
124 }
125
126
127
128
129 if digest != nil {
130 err = x509tools.PkixVerify(cert.PublicKey, si.DigestAlgorithm, si.DigestEncryptionAlgorithm, digest, si.EncryptedDigest)
131 if err == rsa.ErrVerification {
132
133
134
135 err = x509tools.Verify(cert.PublicKey, 0, digest, si.EncryptedDigest)
136 }
137 }
138 return cert, err
139 }
140
141
142
143
144
145
146 func (info Signature) VerifyChain(roots *x509.CertPool, extraCerts []*x509.Certificate, usage x509.ExtKeyUsage, currentTime time.Time) error {
147 pool := x509.NewCertPool()
148 for _, cert := range extraCerts {
149 pool.AddCert(cert)
150 }
151 for _, cert := range info.Intermediates {
152 pool.AddCert(cert)
153 }
154 opts := x509.VerifyOptions{
155 Intermediates: pool,
156 Roots: roots,
157 CurrentTime: currentTime,
158 KeyUsages: []x509.ExtKeyUsage{usage},
159 }
160 _, err := info.Certificate.Verify(opts)
161 return err
162 }
163
View as plain text