-
Notifications
You must be signed in to change notification settings - Fork 163
/
Copy pathrev_info.go
218 lines (183 loc) · 5.74 KB
/
rev_info.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// Copyright 2017 ETH Zurich
// Copyright 2018 ETH Zurich, Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains the Go representation of a revocation info.
package path_mgmt
import (
"context"
"fmt"
"time"
"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/util"
"github.com/scionproto/scion/go/proto"
)
const MinRevTTL = 10 * time.Second // MinRevTTL is the minimum lifetime of a revocation
var _ common.Timeout = (*RevTimeError)(nil)
type RevTimeError string
func NewRevTimeError(r *RevInfo) RevTimeError {
return RevTimeError(fmt.Sprintf(
"Revocation is expired, timestamp: %s, TTL %s.",
util.TimeToCompact(r.Timestamp()), r.TTL()))
}
func (ee RevTimeError) Timeout() bool {
return true
}
func (ee RevTimeError) Error() string {
return string(ee)
}
var _ proto.Cerealizable = (*RevInfo)(nil)
type RevInfo struct {
IfID common.IFIDType
RawIsdas addr.IAInt `capnp:"isdas"`
// LinkType of revocation
LinkType proto.LinkType
// RawTimestamp the issuing timestamp in seconds.
RawTimestamp uint32 `capnp:"timestamp"`
// RawTTL validity period of the revocation in seconds
RawTTL uint32 `capnp:"ttl"`
}
func NewRevInfoFromRaw(b common.RawBytes) (*RevInfo, error) {
r := &RevInfo{}
return r, proto.ParseFromRaw(r, b)
}
func (r *RevInfo) IA() addr.IA {
return r.RawIsdas.IA()
}
// Timestamp returns the issuing time stamp of the revocation.
func (r *RevInfo) Timestamp() time.Time {
return util.SecsToTime(r.RawTimestamp)
}
func (r *RevInfo) TTL() time.Duration {
return time.Duration(r.RawTTL) * time.Second
}
func (r *RevInfo) Expiration() time.Time {
return r.Timestamp().Add(r.TTL())
}
func (r *RevInfo) Active() error {
if r.TTL() < MinRevTTL {
return common.NewBasicError("Revocation TTL smaller than MinRevTTL.", nil,
"TTL", r.TTL().Seconds(), "MinRevTTL", MinRevTTL.Seconds())
}
now := time.Now()
// Revocation is not valid if timestamp is not within the TTL window
if r.Expiration().Before(now) {
return NewRevTimeError(r)
}
if r.Timestamp().After(now.Add(time.Second)) {
return common.NewBasicError("Revocation timestamp is in the future.", nil,
"timestamp", util.TimeToCompact(r.Timestamp()))
}
return nil
}
func (r *RevInfo) ProtoId() proto.ProtoIdType {
return proto.RevInfo_TypeID
}
func (r *RevInfo) Pack() (common.RawBytes, error) {
return proto.PackRoot(r)
}
func (r *RevInfo) String() string {
return fmt.Sprintf("IA: %s IfID: %d Link type: %s Timestamp: %s TTL: %s", r.IA(), r.IfID,
r.LinkType, util.TimeToCompact(r.Timestamp()), r.TTL())
}
// RelativeTTL returns the duration r is still valid for, relative to
// reference. If the revocation is already expired, the returned value is 0.
func (r *RevInfo) RelativeTTL(reference time.Time) time.Duration {
expiration := r.Expiration()
if expiration.Before(reference) {
return 0
}
return expiration.Sub(reference)
}
func (r *RevInfo) Equal(other *RevInfo) bool {
if r == nil || other == nil {
return r == other
}
return r.SameIntf(other) &&
r.RawTimestamp == other.RawTimestamp &&
r.RawTTL == other.RawTTL
}
// SameIntf returns true if r and other both apply to the same interface.
func (r *RevInfo) SameIntf(other *RevInfo) bool {
return r.IfID == other.IfID &&
r.RawIsdas == other.RawIsdas &&
r.LinkType == other.LinkType
}
// Signer is used to sign raw bytes.
type Signer interface {
Sign(msg common.RawBytes) (*proto.SignS, error)
}
// Verifier is used to verify signatures.
type Verifier interface {
// Verify verifies the packed signed revocation based on the signature meta
// data.
Verify(ctx context.Context, msg common.RawBytes, sign *proto.SignS) error
}
var _ proto.Cerealizable = (*SignedRevInfo)(nil)
type SignedRevInfo struct {
Blob common.RawBytes
Sign *proto.SignS
revInfo *RevInfo `capnp:"-"`
}
func NewSignedRevInfoFromRaw(b common.RawBytes) (*SignedRevInfo, error) {
sr := &SignedRevInfo{}
return sr, proto.ParseFromRaw(sr, b)
}
func NewSignedRevInfo(r *RevInfo, signer Signer) (*SignedRevInfo, error) {
rawR, err := r.Pack()
if err != nil {
return nil, err
}
sign, err := signer.Sign(rawR)
if err != nil {
return nil, err
}
return &SignedRevInfo{
Blob: rawR,
Sign: sign,
revInfo: r,
}, nil
}
func (sr *SignedRevInfo) ProtoId() proto.ProtoIdType {
return proto.SignedBlob_TypeID
}
func (sr *SignedRevInfo) RevInfo() (*RevInfo, error) {
var err error
if sr.revInfo == nil {
sr.revInfo, err = NewRevInfoFromRaw(sr.Blob)
}
return sr.revInfo, err
}
// VerifiedRevInfo verifies the signature and returns the revocation
// information or an error in case the verification fails.
func (sr *SignedRevInfo) VerifiedRevInfo(ctx context.Context, verifier Verifier) (*RevInfo, error) {
var err error
if sr.revInfo == nil {
sr.revInfo, err = NewRevInfoFromRaw(sr.Blob)
}
if err != nil {
return sr.revInfo, err
}
return sr.revInfo, verifier.Verify(ctx, sr.Blob, sr.Sign)
}
func (sr *SignedRevInfo) Pack() (common.RawBytes, error) {
return proto.PackRoot(sr)
}
func (sr *SignedRevInfo) String() string {
revInfo, err := sr.RevInfo()
if err != nil {
return fmt.Sprintf("SignedRevInfo: Error parsing RevInfo, Blob: %s Sign: %s", err, sr.Sign)
}
return fmt.Sprintf("SignedRevInfo: RevInfo: %s Sign: %s", revInfo, sr.Sign)
}