1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package signxap
18
19 import (
20 "crypto"
21 "crypto/hmac"
22 "encoding/binary"
23 "errors"
24 "fmt"
25 "io"
26
27 "github.com/sassoftware/relic/lib/authenticode"
28 "github.com/sassoftware/relic/lib/pkcs7"
29 "github.com/sassoftware/relic/lib/pkcs9"
30 "github.com/sassoftware/relic/lib/x509tools"
31 "github.com/sassoftware/relic/signers/sigerrors"
32 )
33
34 type XapSignature struct {
35 pkcs9.TimestampedSignature
36 Hash crypto.Hash
37 }
38
39 func Verify(r io.ReaderAt, size int64, skipDigests bool) (*XapSignature, error) {
40 var tr xapTrailer
41 if err := binary.Read(io.NewSectionReader(r, size-10, 10), binary.LittleEndian, &tr); err != nil {
42 return nil, err
43 }
44 if tr.Magic != trailerMagic {
45 var zipMagic uint32
46 if err := binary.Read(io.NewSectionReader(r, size-22, 4), binary.LittleEndian, &zipMagic); err != nil {
47 return nil, err
48 }
49 if zipMagic == 0x06054b50 {
50 return nil, sigerrors.NotSignedError{Type: "XAP"}
51 }
52 return nil, errors.New("invalid xap file")
53 }
54 size -= int64(tr.TrailerSize) + 10
55 var hdr xapHeader
56 if err := binary.Read(io.NewSectionReader(r, size, 8), binary.LittleEndian, &hdr); err != nil {
57 return nil, err
58 }
59 if hdr.SignatureSize != tr.TrailerSize-8 {
60 return nil, errors.New("invalid xap file")
61 }
62 blob := make([]byte, hdr.SignatureSize)
63 if n, err := r.ReadAt(blob, size+8); err != nil {
64 return nil, err
65 } else if n < len(blob) {
66 return nil, io.ErrUnexpectedEOF
67 }
68 psd, err := pkcs7.Unmarshal(blob)
69 if err != nil {
70 return nil, fmt.Errorf("invalid signature: %s", err)
71 }
72 if !psd.Content.ContentInfo.ContentType.Equal(authenticode.OidSpcIndirectDataContent) {
73 return nil, fmt.Errorf("invalid signature: %s", "not an authenticode signature")
74 }
75 pksig, err := psd.Content.Verify(nil, false)
76 if err != nil {
77 return nil, fmt.Errorf("invalid signature: %s", err)
78 }
79 ts, err := pkcs9.VerifyOptionalTimestamp(pksig)
80 if err != nil {
81 return nil, err
82 }
83 indirect := new(authenticode.SpcIndirectDataContentMsi)
84 if err := psd.Content.ContentInfo.Unmarshal(indirect); err != nil {
85 return nil, fmt.Errorf("invalid signature: %s", err)
86 }
87 hash, err := x509tools.PkixDigestToHashE(indirect.MessageDigest.DigestAlgorithm)
88 if err != nil {
89 return nil, err
90 }
91 if !skipDigests {
92 d := hash.New()
93 if _, err := io.Copy(d, io.NewSectionReader(r, 0, size)); err != nil {
94 return nil, err
95 }
96 calc := d.Sum(nil)
97 expected := indirect.MessageDigest.Digest
98 if !hmac.Equal(calc, expected) {
99 return nil, fmt.Errorf("digest mismatch: calculated %x != found %x", calc, expected)
100 }
101 }
102 return &XapSignature{TimestampedSignature: ts, Hash: hash}, nil
103 }
104
View as plain text