...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package authenticode
18
19 import (
20 "bytes"
21 "context"
22 "crypto"
23 "debug/pe"
24 "encoding/asn1"
25 "encoding/binary"
26 "errors"
27
28 "github.com/sassoftware/relic/lib/binpatch"
29 "github.com/sassoftware/relic/lib/certloader"
30 "github.com/sassoftware/relic/lib/pkcs9"
31 )
32
33
34 func (pd *PEDigest) Sign(ctx context.Context, cert *certloader.Certificate) (*binpatch.PatchSet, *pkcs9.TimestampedSignature, error) {
35 indirect, err := pd.GetIndirect()
36 if err != nil {
37 return nil, nil, err
38 }
39 ts, err := signIndirect(ctx, indirect, pd.Hash, cert)
40 if err != nil {
41 return nil, nil, err
42 }
43 patch, err := pd.MakePatch(ts.Raw)
44 if err != nil {
45 return nil, nil, err
46 }
47 return patch, ts, nil
48 }
49
50 func (pd *PEDigest) GetIndirect() (indirect SpcIndirectDataContentPe, err error) {
51 indirect, err = makePeIndirect(pd.Imprint, pd.Hash, OidSpcPeImageData)
52 if err != nil {
53 return
54 }
55 if len(pd.PageHashes) > 0 {
56 if err2 := pd.imprintPageHashes(&indirect); err2 != nil {
57 err = err2
58 return
59 }
60 }
61 return
62 }
63
64 func (pd *PEDigest) imprintPageHashes(indirect *SpcIndirectDataContentPe) error {
65 var attr SpcAttributePageHashes
66 switch pd.Hash {
67 case crypto.SHA1:
68 attr.Type = OidSpcPageHashV1
69 case crypto.SHA256:
70 attr.Type = OidSpcPageHashV2
71 default:
72 return errors.New("unsupported page hash type")
73 }
74 attr.Hashes = make([][]byte, 1)
75 attr.Hashes[0] = pd.PageHashes
76 blob, err := asn1.Marshal(attr)
77 if err != nil {
78 return err
79 }
80 serdata, err := asn1.Marshal(makeSet(blob))
81 if err != nil {
82 return err
83 }
84 indirect.Data.Value.File = SpcLink{}
85 indirect.Data.Value.File.Moniker.ClassID = SpcUUIDPageHashes
86 indirect.Data.Value.File.Moniker.SerializedData = serdata
87 return nil
88 }
89
90
91
92 func (pd *PEDigest) MakePatch(sig []byte) (*binpatch.PatchSet, error) {
93
94 padded := (len(sig) + 7) / 8 * 8
95 info := certInfo{
96 Length: uint32(8 + padded),
97 Revision: 0x0200,
98 CertificateType: 0x0002,
99 }
100 var buf bytes.Buffer
101 binary.Write(&buf, binary.LittleEndian, info)
102 buf.Write(sig)
103 buf.Write(make([]byte, padded-len(sig)))
104
105 certTbl := buf.Bytes()
106 var dd pe.DataDirectory
107 if pd.OrigSize >= (1 << 32) {
108 return nil, errors.New("PE file is too big")
109 }
110 dd.VirtualAddress = uint32(pd.OrigSize)
111 dd.Size = uint32(len(certTbl))
112 var buf2 bytes.Buffer
113 binary.Write(&buf2, binary.LittleEndian, dd)
114
115 patch := binpatch.New()
116 patch.Add(pd.markers.posDDCert, 8, buf2.Bytes())
117 patch.Add(pd.OrigSize, int64(pd.markers.certSize), certTbl)
118 return patch, nil
119 }
120
121 type certInfo struct {
122 Length uint32
123 Revision uint16
124 CertificateType uint16
125 }
126
View as plain text