1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package signxap
18
19 import (
20 "archive/tar"
21 "bytes"
22 "context"
23 "crypto"
24 "encoding/binary"
25 "errors"
26 "fmt"
27 "io"
28 "io/ioutil"
29
30 "github.com/sassoftware/relic/lib/authenticode"
31 "github.com/sassoftware/relic/lib/binpatch"
32 "github.com/sassoftware/relic/lib/certloader"
33 "github.com/sassoftware/relic/lib/pkcs9"
34 "github.com/sassoftware/relic/lib/zipslicer"
35 )
36
37 type XapDigest struct {
38 Hash crypto.Hash
39 Imprint []byte
40 PatchStart int64
41 PatchLen int64
42 }
43
44 func DigestXapTar(r io.Reader, hash crypto.Hash, doPageHash bool) (*XapDigest, error) {
45 tr := tar.NewReader(r)
46 var cd []byte
47 var totalSize int64
48 for {
49 hdr, err := tr.Next()
50 if err == io.EOF {
51 return nil, errors.New("invalid tarzip")
52 } else if err != nil {
53 return nil, fmt.Errorf("error reading tar: %s", err)
54 }
55 if hdr.Name == zipslicer.TarMemberCD {
56 cd, err = ioutil.ReadAll(tr)
57 if err != nil {
58 return nil, fmt.Errorf("error reading tar: %s", err)
59 }
60 } else if hdr.Name == zipslicer.TarMemberZip {
61 totalSize = hdr.Size
62 break
63 }
64 }
65 bodySize := totalSize - int64(len(cd))
66 d := hash.New()
67 if _, err := io.CopyN(d, tr, bodySize); err != nil {
68 return nil, err
69 }
70 cd = removeSignature(cd)
71 d.Write(cd)
72 zipSize := bodySize + int64(len(cd))
73 return &XapDigest{
74 Hash: hash,
75 Imprint: d.Sum(nil),
76 PatchStart: zipSize,
77 PatchLen: totalSize - zipSize,
78 }, nil
79 }
80
81 func removeSignature(cd []byte) []byte {
82 size := len(cd)
83 var tr xapTrailer
84 binary.Read(bytes.NewReader(cd[size-10:size]), binary.LittleEndian, &tr)
85 if tr.Magic == trailerMagic {
86 size -= int(tr.TrailerSize) + 10
87 return cd[:size]
88 }
89 return cd
90 }
91
92 func (d *XapDigest) Sign(ctx context.Context, cert *certloader.Certificate) (*binpatch.PatchSet, *pkcs9.TimestampedSignature, error) {
93 ts, err := authenticode.SignSip(ctx, d.Imprint, d.Hash, xapSipInfo, cert)
94 if err != nil {
95 return nil, nil, err
96 }
97 var w bytes.Buffer
98 hdr := xapHeader{
99 Unknown1: 1,
100 Unknown2: 1,
101 SignatureSize: uint32(len(ts.Raw)),
102 }
103 binary.Write(&w, binary.LittleEndian, hdr)
104 w.Write(ts.Raw)
105 tr := xapTrailer{
106 Magic: trailerMagic,
107 Unknown1: 1,
108 TrailerSize: uint32(len(ts.Raw) + 8),
109 }
110 binary.Write(&w, binary.LittleEndian, tr)
111 patch := binpatch.New()
112 patch.Add(d.PatchStart, d.PatchLen, w.Bytes())
113 return patch, ts, nil
114 }
115
View as plain text