-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathplatform.go
More file actions
207 lines (178 loc) · 7.89 KB
/
platform.go
File metadata and controls
207 lines (178 loc) · 7.89 KB
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
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2021 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package secboot
import (
"crypto"
"fmt"
"sort"
)
// PlatformHandlerErrorType indicates the type of error that
// PlatformHandlerError is associated with.
type PlatformHandlerErrorType int
const (
// PlatformHandlerErrorInvalidData indicates that an action could not be
// performed by PlatformKeyDataHandler because the supplied key data is
// invalid.
PlatformHandlerErrorInvalidData PlatformHandlerErrorType = iota + 1
// PlatformHandlerErrorUninitialized indicates that an action could not
// be performed by PlatformKeyDataHandler because the platform's secure
// device is not properly initialized.
PlatformHandlerErrorUninitialized
// PlatformHandlerErrorUnavailable indicates that an action could not be
// be performed by PlatformKeyDataHandler because the platform's secure
// device is unavailable.
PlatformHandlerErrorUnavailable
// PlatformHandlerErrorInvalidAuthKey indicates that an action could not
// be performed by PlatformKeyDataHandler because the supplied
// authorization key was incorrect.
// TODO: Rename this to PlatformHandlerErrorInvalidUserAuthKey
PlatformHandlerErrorInvalidAuthKey
// PlatformHandlerErrorUserAuthUnavailable indicates that an action could
// not be performed by PlatformKeyDataHandler because user authorization
// is currently unavailable.
PlatformHandlerErrorUserAuthUnavailable
// PlatformHandlerErrorIncompatibleRole indicates that an action could
// not be performed by PlatformKeyDataHandler because the key data's
// role is incompatible with the current boot configuration.
PlatformHandlerErrorIncompatibleRole
// PlatformHandlerInvalidRoleParams indicates that an action could
// not be performed by PlatformKeyDataHandler because the key data's
// role parameters are invalid.
PlatformHandlerErrorInvalidRoleParams
)
// PlatformHandlerError is returned from a PlatformKeyDataHandler implementation when
// the type of error can be categorized as one of the types supported by
// PlatformHandlerErrorType.
type PlatformHandlerError struct {
Type PlatformHandlerErrorType // type of the error
Err error // underlying error
}
func (e *PlatformHandlerError) Error() string {
return e.Err.Error()
}
func (e *PlatformHandlerError) Unwrap() error {
return e.Err
}
// PlatformKeyData represents the data exchanged between this package and
// platform implementations via the PlatformKeyDataHandler.
type PlatformKeyData struct {
Generation int
EncodedHandle []byte // The JSON encoded platform handle
Role string
KDFAlg crypto.Hash
AuthMode AuthMode
}
// PlatformKeyDataHandlerFlags can be used to describe features supported
// by a registered platform.
//
// The lower 40 bits are for use and defined by the platform, and the
// platform can choose to use them however it wants to (eg, it may use some
// bits as a version number). This package does not use or interpret these
// 40 bits.
//
// The upper 24 bits are reserved for common flags defined by this package,
// although there aren't any defined right now.
type PlatformKeyDataHandlerFlags uint64
const (
platformKeyDataHandlerCommonFlagsMask uint64 = 0xffffff0000000000
// PlatformProtectedByStorageContainer indicates that a platform protects
// its keys inside an encrypted storage container rather than a hardware
// device.
PlatformProtectedByStorageContainer PlatformKeyDataHandlerFlags = 1 << 40
)
// AddPlatformFlags adds the platform defined flags to the common flags,
// returning a new flags value. This package doesn't define the meaning of
// the specified flags and it does not use or interpret them in any way.
//
// This will panic if it uses any of the upper 24 bits reserved for common
// flags defined by this package.
func (f PlatformKeyDataHandlerFlags) AddPlatformFlags(flags uint64) PlatformKeyDataHandlerFlags {
if flags&platformKeyDataHandlerCommonFlagsMask > 0 {
panic(fmt.Sprintf("platform is using flag bits reserved for common flags: %#x", flags&platformKeyDataHandlerCommonFlagsMask))
}
return f | PlatformKeyDataHandlerFlags(flags)
}
type platformKeyDataHandlerInfo struct {
handler PlatformKeyDataHandler
flags PlatformKeyDataHandlerFlags
}
// PlatormKeyDataHandler is the interface that this go package uses to
// interact with a platform's secure device for the purpose of recovering keys.
type PlatformKeyDataHandler interface {
// RecoverKeys attempts to recover the cleartext keys from the supplied encrypted
// payload using this platform's secure device.
RecoverKeys(data *PlatformKeyData, encryptedPayload []byte) ([]byte, error)
// RecoverKeysWithAuthKey attempts to recover the cleartext keys from the
// encrypted payload using this platform's secure device. The key parameter
// is a passphrase derived key to enable passphrase support to be integrated
// with the secure device. The platform implementation doesn't provide the primary
// mechanism of protecting keys with a passphrase - this is done in the platform
// agnostic API. Some devices (such as TPMs) support this integration natively. For
// other devices, the integration should provide a way of validating the key in
// a way that requires the use of the secure device (eg, such as computing a HMAC of
// it using a hardware backed key).
RecoverKeysWithAuthKey(data *PlatformKeyData, encryptedPayload, key []byte) ([]byte, error)
// ChangeAuthKey is called to notify the platform implementation that the
// passphrase is being changed. The old and new parameters are passphrase derived
// keys. Either value can be nil if passphrase authentication is being enabled (
// where old will be nil) or disabled (where new will be nil).
//
// The use of the context argument isn't defined here - it's passed during
// key construction and the platform is free to use it however it likes.
//
// On success, it should return an updated handle.
ChangeAuthKey(data *PlatformKeyData, old, new []byte, context any) ([]byte, error)
}
var keyDataHandlers = make(map[string]platformKeyDataHandlerInfo)
// RegisterPlatformKeyDataHandler registers a handler for the specified platform name.
// The platform can also specify a set of feature flags.
//
// Supplying a nil handler will unregister the handler for the specified platform name,
// if one exists.
func RegisterPlatformKeyDataHandler(name string, handler PlatformKeyDataHandler, flags PlatformKeyDataHandlerFlags) {
if handler == nil {
delete(keyDataHandlers, name)
return
}
keyDataHandlers[name] = platformKeyDataHandlerInfo{
handler: handler,
flags: flags,
}
}
// RegisteredPlatformKeyDataHandler returns the handler and its flags, for the
// specified platform name.
//
// If no platform with the specified name is registered, a ErrNoPlatformHandlerRegistered
// error will be returned.
func RegisteredPlatformKeyDataHandler(name string) (handler PlatformKeyDataHandler, flags PlatformKeyDataHandlerFlags, err error) {
handlerInfo, exists := keyDataHandlers[name]
if !exists {
return nil, 0, ErrNoPlatformHandlerRegistered
}
return handlerInfo.handler, handlerInfo.flags, nil
}
// ListRegisteredKeyDataPlatforms returns a list of the names of all
// of the registered PlatformKeyDataHandlers.
func ListRegisteredKeyDataPlatforms() []string {
var platforms []string
for k := range keyDataHandlers {
platforms = append(platforms, k)
}
sort.Strings(platforms)
return platforms
}