1 package verify
2
3 import (
4 "encoding/json"
5 "strings"
6 "time"
7
8 "github.com/secure-systems-lab/go-securesystemslib/cjson"
9 "github.com/theupdateframework/go-tuf/data"
10 "github.com/theupdateframework/go-tuf/internal/roles"
11 "github.com/theupdateframework/go-tuf/pkg/keys"
12 )
13
14 type signedMeta struct {
15 Type string `json:"_type"`
16 Expires time.Time `json:"expires"`
17 Version int64 `json:"version"`
18 }
19
20
21
22
23 func VerifySignature(signed json.RawMessage, sig data.HexBytes,
24 verifier keys.Verifier) error {
25 var decoded map[string]interface{}
26 if err := json.Unmarshal(signed, &decoded); err != nil {
27 return err
28 }
29 msg, err := cjson.EncodeCanonical(decoded)
30 if err != nil {
31 return err
32 }
33 return verifier.Verify(msg, sig)
34 }
35
36 func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion int64) error {
37 if err := db.VerifySignatures(s, role); err != nil {
38 return err
39 }
40
41 sm := &signedMeta{}
42 if err := json.Unmarshal(s.Signed, sm); err != nil {
43 return err
44 }
45
46 if roles.IsTopLevelRole(role) {
47
48
49 if !strings.EqualFold(sm.Type, role) {
50 return ErrWrongMetaType
51 }
52 } else {
53
54 if strings.ToLower(sm.Type) != "targets" {
55 return ErrWrongMetaType
56 }
57 }
58
59 if sm.Version < minVersion {
60 return ErrLowVersion{sm.Version, minVersion}
61 }
62
63 return nil
64 }
65
66 func (db *DB) Verify(s *data.Signed, role string, minVersion int64) error {
67
68 err := db.VerifyIgnoreExpiredCheck(s, role, minVersion)
69
70 if err != nil {
71 return err
72 }
73
74 sm := &signedMeta{}
75 if err := json.Unmarshal(s.Signed, sm); err != nil {
76 return err
77 }
78
79 if IsExpired(sm.Expires) {
80 return ErrExpired{sm.Expires}
81 }
82
83 return nil
84 }
85
86 var IsExpired = func(t time.Time) bool {
87 return time.Until(t) <= 0
88 }
89
90 func (db *DB) VerifySignatures(s *data.Signed, role string) error {
91 if len(s.Signatures) == 0 {
92 return ErrNoSignatures
93 }
94
95 roleData := db.GetRole(role)
96 if roleData == nil {
97 return ErrUnknownRole{role}
98 }
99
100
101
102
103 verifiedKeyIDs := make(map[string]struct{})
104 numVerifiedKeys := 0
105 for _, sig := range s.Signatures {
106 if !roleData.ValidKey(sig.KeyID) {
107 continue
108 }
109 verifier, err := db.GetVerifier(sig.KeyID)
110 if err != nil {
111 continue
112 }
113
114 if err := VerifySignature(s.Signed, sig.Signature, verifier); err != nil {
115
116
117
118
119
120 continue
121 }
122
123
124
125
126
127
128 keyIDs := verifier.MarshalPublicKey().IDs()
129 wasKeySeen := false
130 for _, keyID := range keyIDs {
131 if _, present := verifiedKeyIDs[keyID]; present {
132 wasKeySeen = true
133 }
134 }
135 if !wasKeySeen {
136 for _, id := range keyIDs {
137 verifiedKeyIDs[id] = struct{}{}
138 }
139
140 numVerifiedKeys++
141 }
142 }
143 if numVerifiedKeys < roleData.Threshold {
144 return ErrRoleThreshold{roleData.Threshold, numVerifiedKeys}
145 }
146
147 return nil
148 }
149
150 func (db *DB) Unmarshal(b []byte, v interface{}, role string, minVersion int64) error {
151 s := &data.Signed{}
152 if err := json.Unmarshal(b, s); err != nil {
153 return err
154 }
155 if err := db.Verify(s, role, minVersion); err != nil {
156 return err
157 }
158 return json.Unmarshal(s.Signed, v)
159 }
160
161
162 func (db *DB) UnmarshalIgnoreExpired(b []byte, v interface{}, role string, minVersion int64) error {
163 s := &data.Signed{}
164 if err := json.Unmarshal(b, s); err != nil {
165 return err
166 }
167
168
169 verifyErr := db.Verify(s, role, minVersion)
170 if verifyErr != nil {
171 if _, ok := verifyErr.(ErrExpired); !ok {
172 return verifyErr
173 }
174 }
175 return json.Unmarshal(s.Signed, v)
176 }
177
178 func (db *DB) UnmarshalTrusted(b []byte, v interface{}, role string) error {
179 s := &data.Signed{}
180 if err := json.Unmarshal(b, s); err != nil {
181 return err
182 }
183 if err := db.VerifySignatures(s, role); err != nil {
184 return err
185 }
186 return json.Unmarshal(s.Signed, v)
187 }
188
View as plain text