1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package msi
18
19
20
21 import (
22 "io"
23 "io/ioutil"
24 "os"
25
26 "github.com/sassoftware/relic/lib/atomicfile"
27 "github.com/sassoftware/relic/lib/authenticode"
28 "github.com/sassoftware/relic/lib/certloader"
29 "github.com/sassoftware/relic/lib/comdoc"
30 "github.com/sassoftware/relic/lib/magic"
31 "github.com/sassoftware/relic/signers"
32 )
33
34 var MsiSigner = &signers.Signer{
35 Name: "msi",
36 Aliases: []string{"msi-tar"},
37 Magic: magic.FileTypeMSI,
38 CertTypes: signers.CertTypeX509,
39 Transform: transform,
40 Sign: sign,
41 Verify: verify,
42 }
43
44 func init() {
45 MsiSigner.Flags().Bool("no-extended-sig", false, "(MSI) Don't emit a MsiDigitalSignatureEx digest")
46 signers.Register(MsiSigner)
47 }
48
49 type msiTransformer struct {
50 f *os.File
51 cdf *comdoc.ComDoc
52 exsig []byte
53 }
54
55 func transform(f *os.File, opts signers.SignOpts) (signers.Transformer, error) {
56 cdf, err := comdoc.ReadFile(f)
57 if err != nil {
58 return nil, err
59 }
60 var exsig []byte
61 noExtended := opts.Flags.GetBool("no-extended-sig")
62 if !noExtended {
63 exsig, err = authenticode.PrehashMSI(cdf, opts.Hash)
64 if err != nil {
65 return nil, err
66 }
67 }
68 return &msiTransformer{f, cdf, exsig}, nil
69 }
70
71
72 func (t *msiTransformer) GetReader() (io.Reader, error) {
73 r, w := io.Pipe()
74 go func() {
75 w.CloseWithError(authenticode.MsiToTar(t.cdf, w))
76 }()
77 return r, nil
78 }
79
80
81 func (t *msiTransformer) Apply(dest, mimeType string, result io.Reader) error {
82 t.cdf.Close()
83 blob, err := ioutil.ReadAll(result)
84 if err != nil {
85 return err
86 }
87
88 f, err := atomicfile.WriteInPlace(t.f, dest)
89 if err != nil {
90 return err
91 }
92 defer f.Close()
93 cdf, err := comdoc.WriteFile(f.GetFile())
94 if err != nil {
95 return err
96 }
97 if err := authenticode.InsertMSISignature(cdf, blob, t.exsig); err != nil {
98 return err
99 }
100 if err := cdf.Close(); err != nil {
101 return err
102 }
103 return f.Commit()
104 }
105
106
107 func sign(r io.Reader, cert *certloader.Certificate, opts signers.SignOpts) ([]byte, error) {
108 noExtended := opts.Flags.GetBool("no-extended-sig")
109 sum, err := authenticode.DigestMsiTar(r, opts.Hash, !noExtended)
110 if err != nil {
111 return nil, err
112 }
113 ts, err := authenticode.SignMSIImprint(opts.Context(), sum, opts.Hash, cert)
114 if err != nil {
115 return nil, err
116 }
117 return opts.SetPkcs7(ts)
118 }
119
120 func verify(f *os.File, opts signers.VerifyOpts) ([]*signers.Signature, error) {
121 sig, err := authenticode.VerifyMSI(f, opts.NoDigests)
122 if err != nil {
123 return nil, err
124 }
125 return []*signers.Signature{&signers.Signature{
126 Hash: sig.HashFunc,
127 X509Signature: &sig.TimestampedSignature,
128 }}, nil
129 }
130
View as plain text