1 package pkcs7
2
3 import (
4 "crypto/subtle"
5 "crypto/x509"
6 "crypto/x509/pkix"
7 "encoding/asn1"
8 "errors"
9 "fmt"
10 "time"
11 )
12
13
14
15
16 func (p7 *PKCS7) Verify() (err error) {
17 return p7.VerifyWithChain(nil)
18 }
19
20
21
22
23
24
25
26
27 func (p7 *PKCS7) VerifyWithChain(truststore *x509.CertPool) (err error) {
28 intermediates := x509.NewCertPool()
29 for _, cert := range(p7.Certificates) {
30 intermediates.AddCert(cert)
31 }
32
33 opts := x509.VerifyOptions{
34 Roots: truststore,
35 Intermediates: intermediates,
36 }
37
38 return p7.VerifyWithOpts(opts)
39 }
40
41
42
43
44
45
46
47 func (p7 *PKCS7) VerifyWithChainAtTime(truststore *x509.CertPool, currentTime time.Time) (err error) {
48 intermediates := x509.NewCertPool()
49 for _, cert := range(p7.Certificates) {
50 intermediates.AddCert(cert)
51 }
52
53 opts := x509.VerifyOptions{
54 Roots: truststore,
55 Intermediates: intermediates,
56 CurrentTime: currentTime,
57 }
58
59 return p7.VerifyWithOpts(opts)
60 }
61
62
63
64
65
66
67
68
69
70
71
72
73
74 func (p7 *PKCS7) VerifyWithOpts(opts x509.VerifyOptions) (err error) {
75
76 if opts.KeyUsages == nil {
77 opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
78 }
79
80 if len(p7.Signers) == 0 {
81 return errors.New("pkcs7: Message has no signers")
82 }
83
84
85
86 if opts.CurrentTime.IsZero() {
87 for _, signer := range p7.Signers {
88 if err := verifySignature(p7, signer, opts); err != nil {
89 return err
90 }
91 }
92 return nil
93 }
94
95
96 for _, signer := range p7.Signers {
97 if err := verifySignatureAtTime(p7, signer, opts); err != nil {
98 return err
99 }
100 }
101 return nil
102 }
103
104 func verifySignatureAtTime(p7 *PKCS7, signer signerInfo, opts x509.VerifyOptions) (err error) {
105 signedData := p7.Content
106 ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
107 if ee == nil {
108 return errors.New("pkcs7: No certificate for signer")
109 }
110 if len(signer.AuthenticatedAttributes) > 0 {
111
112 var (
113 digest []byte
114 signingTime time.Time
115 )
116 err := unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeMessageDigest, &digest)
117 if err != nil {
118 return err
119 }
120 hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
121 if err != nil {
122 return err
123 }
124 h := hash.New()
125 h.Write(p7.Content)
126 computed := h.Sum(nil)
127 if subtle.ConstantTimeCompare(digest, computed) != 1 {
128 return &MessageDigestMismatchError{
129 ExpectedDigest: digest,
130 ActualDigest: computed,
131 }
132 }
133 signedData, err = marshalAttributes(signer.AuthenticatedAttributes)
134 if err != nil {
135 return err
136 }
137 err = unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeSigningTime, &signingTime)
138 if err == nil {
139
140 if signingTime.After(ee.NotAfter) || signingTime.Before(ee.NotBefore) {
141 return fmt.Errorf("pkcs7: signing time %q is outside of certificate validity %q to %q",
142 signingTime.Format(time.RFC3339),
143 ee.NotBefore.Format(time.RFC3339),
144 ee.NotAfter.Format(time.RFC3339))
145 }
146 }
147 }
148 if opts.Roots != nil {
149 _, err = ee.Verify(opts)
150 if err != nil {
151 return fmt.Errorf("pkcs7: failed to verify certificate chain: %v", err)
152 }
153 }
154 sigalg, err := getSignatureAlgorithm(signer.DigestEncryptionAlgorithm, signer.DigestAlgorithm)
155 if err != nil {
156 return err
157 }
158 return ee.CheckSignature(sigalg, signedData, signer.EncryptedDigest)
159 }
160
161 func verifySignature(p7 *PKCS7, signer signerInfo, opts x509.VerifyOptions) (err error) {
162 signedData := p7.Content
163 ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
164 if ee == nil {
165 return errors.New("pkcs7: No certificate for signer")
166 }
167 signingTime := time.Now().UTC()
168 if len(signer.AuthenticatedAttributes) > 0 {
169
170 var digest []byte
171 err := unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeMessageDigest, &digest)
172 if err != nil {
173 return err
174 }
175 hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
176 if err != nil {
177 return err
178 }
179 h := hash.New()
180 h.Write(p7.Content)
181 computed := h.Sum(nil)
182 if subtle.ConstantTimeCompare(digest, computed) != 1 {
183 return &MessageDigestMismatchError{
184 ExpectedDigest: digest,
185 ActualDigest: computed,
186 }
187 }
188 signedData, err = marshalAttributes(signer.AuthenticatedAttributes)
189 if err != nil {
190 return err
191 }
192 err = unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeSigningTime, &signingTime)
193 if err == nil {
194
195 if signingTime.After(ee.NotAfter) || signingTime.Before(ee.NotBefore) {
196 return fmt.Errorf("pkcs7: signing time %q is outside of certificate validity %q to %q",
197 signingTime.Format(time.RFC3339),
198 ee.NotBefore.Format(time.RFC3339),
199 ee.NotAfter.Format(time.RFC3339))
200 }
201 }
202 }
203 if opts.Roots != nil {
204 opts.CurrentTime = signingTime
205 _, err = ee.Verify(opts)
206 if err != nil {
207 return fmt.Errorf("pkcs7: failed to verify certificate chain: %v", err)
208 }
209 }
210 sigalg, err := getSignatureAlgorithm(signer.DigestEncryptionAlgorithm, signer.DigestAlgorithm)
211 if err != nil {
212 return err
213 }
214 return ee.CheckSignature(sigalg, signedData, signer.EncryptedDigest)
215 }
216
217
218
219 func (p7 *PKCS7) GetOnlySigner() *x509.Certificate {
220 if len(p7.Signers) != 1 {
221 return nil
222 }
223 signer := p7.Signers[0]
224 return getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
225 }
226
227
228 func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error {
229 sd, ok := p7.raw.(signedData)
230 if !ok {
231 return errors.New("pkcs7: payload is not signedData content")
232 }
233 if len(sd.SignerInfos) < 1 {
234 return errors.New("pkcs7: payload has no signers")
235 }
236 attributes := sd.SignerInfos[0].AuthenticatedAttributes
237 return unmarshalAttribute(attributes, attributeType, out)
238 }
239
240 func parseSignedData(data []byte) (*PKCS7, error) {
241 var sd signedData
242 asn1.Unmarshal(data, &sd)
243 certs, err := sd.Certificates.Parse()
244 if err != nil {
245 return nil, err
246 }
247
248
249 var compound asn1.RawValue
250 var content unsignedData
251
252
253 if len(sd.ContentInfo.Content.Bytes) > 0 {
254 if _, err := asn1.Unmarshal(sd.ContentInfo.Content.Bytes, &compound); err != nil {
255 return nil, err
256 }
257 }
258
259 if compound.IsCompound {
260 if compound.Tag == 4 {
261 if _, err = asn1.Unmarshal(compound.Bytes, &content); err != nil {
262 return nil, err
263 }
264 } else {
265 content = compound.Bytes
266 }
267 } else {
268
269 content = compound.Bytes
270 }
271 return &PKCS7{
272 Content: content,
273 Certificates: certs,
274 CRLs: sd.CRLs,
275 Signers: sd.SignerInfos,
276 raw: sd}, nil
277 }
278
279
280
281 type MessageDigestMismatchError struct {
282 ExpectedDigest []byte
283 ActualDigest []byte
284 }
285
286 func (err *MessageDigestMismatchError) Error() string {
287 return fmt.Sprintf("pkcs7: Message digest mismatch\n\tExpected: %X\n\tActual : %X", err.ExpectedDigest, err.ActualDigest)
288 }
289
290 func getSignatureAlgorithm(digestEncryption, digest pkix.AlgorithmIdentifier) (x509.SignatureAlgorithm, error) {
291 switch {
292 case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA1):
293 return x509.ECDSAWithSHA1, nil
294 case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA256):
295 return x509.ECDSAWithSHA256, nil
296 case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA384):
297 return x509.ECDSAWithSHA384, nil
298 case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA512):
299 return x509.ECDSAWithSHA512, nil
300 case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSA),
301 digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA1),
302 digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA256),
303 digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA384),
304 digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA512):
305 switch {
306 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
307 return x509.SHA1WithRSA, nil
308 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
309 return x509.SHA256WithRSA, nil
310 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA384):
311 return x509.SHA384WithRSA, nil
312 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA512):
313 return x509.SHA512WithRSA, nil
314 default:
315 return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
316 digest.Algorithm.String(), digestEncryption.Algorithm.String())
317 }
318 case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmDSA),
319 digestEncryption.Algorithm.Equal(OIDDigestAlgorithmDSASHA1):
320 switch {
321 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
322 return x509.DSAWithSHA1, nil
323 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
324 return x509.DSAWithSHA256, nil
325 default:
326 return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
327 digest.Algorithm.String(), digestEncryption.Algorithm.String())
328 }
329 case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP256),
330 digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP384),
331 digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP521):
332 switch {
333 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
334 return x509.ECDSAWithSHA1, nil
335 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
336 return x509.ECDSAWithSHA256, nil
337 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA384):
338 return x509.ECDSAWithSHA384, nil
339 case digest.Algorithm.Equal(OIDDigestAlgorithmSHA512):
340 return x509.ECDSAWithSHA512, nil
341 default:
342 return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
343 digest.Algorithm.String(), digestEncryption.Algorithm.String())
344 }
345 case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmEDDSA25519):
346 return x509.PureEd25519, nil
347 default:
348 return -1, fmt.Errorf("pkcs7: unsupported algorithm %q",
349 digestEncryption.Algorithm.String())
350 }
351 }
352
353 func getCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate {
354 for _, cert := range certs {
355 if isCertMatchForIssuerAndSerial(cert, ias) {
356 return cert
357 }
358 }
359 return nil
360 }
361
362 func unmarshalAttribute(attrs []attribute, attributeType asn1.ObjectIdentifier, out interface{}) error {
363 for _, attr := range attrs {
364 if attr.Type.Equal(attributeType) {
365 _, err := asn1.Unmarshal(attr.Value.Bytes, out)
366 return err
367 }
368 }
369 return errors.New("pkcs7: attribute type not in attributes")
370 }
371
View as plain text