1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package authenticode
18
19 import (
20 "context"
21 "crypto"
22 "crypto/hmac"
23 "errors"
24 "fmt"
25 "io"
26
27 "github.com/sassoftware/relic/lib/binpatch"
28 "github.com/sassoftware/relic/lib/cabfile"
29 "github.com/sassoftware/relic/lib/certloader"
30 "github.com/sassoftware/relic/lib/pkcs7"
31 "github.com/sassoftware/relic/lib/pkcs9"
32 "github.com/sassoftware/relic/lib/x509tools"
33 "github.com/sassoftware/relic/signers/sigerrors"
34 )
35
36 type CabSignature struct {
37 pkcs9.TimestampedSignature
38 Indirect *SpcIndirectDataContentPe
39 HashFunc crypto.Hash
40 PatchSet *binpatch.PatchSet
41 }
42
43
44 func VerifyCab(f io.ReaderAt, skipDigests bool) (*CabSignature, error) {
45 cab, err := cabfile.Parse(io.NewSectionReader(f, 0, 1<<63-1))
46 if err != nil {
47 return nil, err
48 }
49 if len(cab.Signature) == 0 {
50 return nil, sigerrors.NotSignedError{Type: "cabinet"}
51 }
52 psd, err := pkcs7.Unmarshal(cab.Signature)
53 if err != nil {
54 return nil, err
55 }
56 if !psd.Content.ContentInfo.ContentType.Equal(OidSpcIndirectDataContent) {
57 return nil, errors.New("not an authenticode signature")
58 }
59 pksig, err := psd.Content.Verify(nil, false)
60 if err != nil {
61 return nil, err
62 }
63 ts, err := pkcs9.VerifyOptionalTimestamp(pksig)
64 if err != nil {
65 return nil, err
66 }
67 indirect := new(SpcIndirectDataContentPe)
68 if err := psd.Content.ContentInfo.Unmarshal(indirect); err != nil {
69 return nil, err
70 }
71 hash, err := x509tools.PkixDigestToHashE(indirect.MessageDigest.DigestAlgorithm)
72 if err != nil {
73 return nil, err
74 }
75 cabsig := &CabSignature{
76 TimestampedSignature: ts,
77 Indirect: indirect,
78 HashFunc: hash,
79 }
80 if !skipDigests {
81 digest, err := cabfile.Digest(io.NewSectionReader(f, 0, 1<<63-1), hash)
82 if err != nil {
83 return nil, err
84 }
85 if !hmac.Equal(digest.Imprint, indirect.MessageDigest.Digest) {
86 return nil, fmt.Errorf("digest mismatch: %x != %x", digest.Imprint, indirect.MessageDigest.Digest)
87 }
88
89
90
91 }
92 return cabsig, nil
93 }
94
95
96 func SignCabImprint(ctx context.Context, digest *cabfile.CabinetDigest, cert *certloader.Certificate) (*binpatch.PatchSet, *pkcs9.TimestampedSignature, error) {
97 indirect, err := makePeIndirect(digest.Imprint, digest.HashFunc, OidSpcCabImageData)
98 if err != nil {
99 return nil, nil, err
100 }
101 ts, err := signIndirect(ctx, indirect, digest.HashFunc, cert)
102 if err != nil {
103 return nil, nil, err
104 }
105 patch := digest.MakePatch(ts.Raw)
106 return patch, ts, nil
107 }
108
View as plain text