1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package appmanifest
18
19 import (
20 "crypto"
21 "crypto/x509"
22 "encoding/base64"
23 "errors"
24 "fmt"
25
26 "github.com/beevik/etree"
27 "github.com/sassoftware/relic/lib/pkcs7"
28 "github.com/sassoftware/relic/lib/pkcs9"
29 "github.com/sassoftware/relic/lib/x509tools"
30 "github.com/sassoftware/relic/lib/xmldsig"
31 "github.com/sassoftware/relic/signers/sigerrors"
32 )
33
34 type ManifestSignature struct {
35 Signature *pkcs9.TimestampedSignature
36 Hash crypto.Hash
37 AssemblyName string
38 AssemblyVersion string
39 PublicKeyToken string
40 }
41
42
43 func Verify(manifest []byte) (*ManifestSignature, error) {
44 doc := etree.NewDocument()
45 if err := doc.ReadFromString(string(manifest)); err != nil {
46 return nil, err
47 }
48 root := doc.Root()
49 primary, err := xmldsig.Verify(root, "Signature", nil)
50 if err != nil {
51 if _, ok := err.(sigerrors.NotSignedError); ok {
52 return nil, err
53 }
54 return nil, fmt.Errorf("invalid primary signature: %s", err)
55 }
56 license := root.FindElement("Signature/KeyInfo/msrel:RelData/r:license")
57 if license == nil {
58 return nil, sigerrors.NotSignedError{Type: "application manifest"}
59 }
60 secondary, err := xmldsig.Verify(license, "issuer/Signature", nil)
61 if err != nil {
62 if _, ok := err.(sigerrors.NotSignedError); ok {
63 return nil, err
64 }
65 return nil, fmt.Errorf("invalid authenticode signature: %s", err)
66 }
67 if !x509tools.SameKey(primary.PublicKey, secondary.PublicKey) {
68 return nil, errors.New("signatures were made with different keys")
69 }
70 asi := root.SelectElement("assemblyIdentity")
71 if asi == nil {
72 return nil, errors.New("missing assemblyIdentity")
73 }
74 token, err := PublicKeyToken(primary.PublicKey)
75 if err != nil {
76 return nil, err
77 }
78 if token2 := asi.SelectAttrValue("publicKeyToken", ""); token2 != token {
79 return nil, fmt.Errorf("publicKeyToken mismatch: expected %s, got %s", token, token2)
80 }
81 sig := pkcs7.Signature{Intermediates: secondary.Certificates, Certificate: secondary.Leaf()}
82 if sig.Certificate == nil {
83 return nil, errors.New("leaf x509 certificate not found")
84 }
85 ts := &pkcs9.TimestampedSignature{Signature: sig}
86 if tse := license.FindElement("r:issuer/Signature/Object/as:Timestamp"); tse != nil {
87 blob, err := base64.StdEncoding.DecodeString(tse.Text())
88 if err != nil {
89 return nil, fmt.Errorf("invalid timestamp: %s", err)
90 }
91 timestamp, err := pkcs7.Unmarshal(blob)
92 if err != nil {
93 return nil, fmt.Errorf("invalid timestamp: %s", err)
94 }
95
96 cs, err := VerifyTimestamp(timestamp, secondary.EncryptedDigest, secondary.Certificates)
97 if err != nil {
98 return nil, fmt.Errorf("invalid timestamp: %s", err)
99 }
100 ts.CounterSignature = cs
101 }
102 return &ManifestSignature{
103 Signature: ts,
104 AssemblyName: asi.SelectAttrValue("name", ""),
105 AssemblyVersion: asi.SelectAttrValue("version", ""),
106 Hash: primary.Hash,
107 PublicKeyToken: token,
108 }, nil
109 }
110
111 func VerifyTimestamp(timestamp *pkcs7.ContentInfoSignedData, encryptedDigest []byte, extraCerts []*x509.Certificate) (*pkcs9.CounterSignature, error) {
112 var cs *pkcs9.CounterSignature
113 var err error
114
115 if timestamp.Content.ContentInfo.ContentType.Equal(pkcs9.OidTSTInfo) {
116
117 cs, err = pkcs9.Verify(timestamp, encryptedDigest, extraCerts)
118 } else {
119
120 cs, err = pkcs9.VerifyMicrosoftToken(timestamp, encryptedDigest)
121 }
122
123 return cs, err
124 }
125
View as plain text