forked from canonical/secboot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeydata_luks.go
147 lines (125 loc) · 4.35 KB
/
keydata_luks.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
// -*- 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 (
"bytes"
"errors"
"golang.org/x/xerrors"
"github.com/snapcore/secboot/internal/luks2"
"github.com/snapcore/secboot/internal/luksview"
)
// LUKS2KeyDataReader provides a mechanism to read a KeyData from a LUKS2 token.
type LUKS2KeyDataReader struct {
name string
slot int
priority int
*bytes.Reader
}
// NewLUKS2KeyDataReader is used to read a LUKS2 token containing key data with
// the specified name on the specified LUKS2 container.
func NewLUKS2KeyDataReader(devicePath, name string) (*LUKS2KeyDataReader, error) {
view, err := newLUKSView(devicePath, luks2.LockModeBlocking)
if err != nil {
return nil, xerrors.Errorf("cannot obtain LUKS2 header view: %w", err)
}
token, _, exists := view.TokenByName(name)
if !exists {
return nil, errors.New("a keyslot with the specified name does not exist")
}
kdToken, ok := token.(*luksview.KeyDataToken)
if !ok {
return nil, errors.New("named keyslot has the wrong type")
}
if kdToken.Data == nil {
return nil, errors.New("named keyslot does not contain key data yet")
}
return &LUKS2KeyDataReader{
name: devicePath + ":" + name,
slot: token.Keyslots()[0],
priority: kdToken.Priority,
Reader: bytes.NewReader(kdToken.Data)}, nil
}
func (r *LUKS2KeyDataReader) ReadableName() string {
return r.name
}
// KeyslotID indicates the keyslot ID associated with the token from which this
// KeyData is read.
func (r *LUKS2KeyDataReader) KeyslotID() int {
return r.slot
}
// Priority indicates the priority of the keyslot associated with the token from
// which this KeyData is read. The default priority is 0 with higher numbers
// indicating a higher priority.
func (r *LUKS2KeyDataReader) Priority() int {
return r.priority
}
// LUKS2KeyDataWriter provides a mechanism to write a KeyData to a LUKS2 token.
type LUKS2KeyDataWriter struct {
devicePath string
id int
slot int
name string
priority int
*bytes.Buffer
}
// NewLUKS2KeyDataWriter creates a new LUKS2KeyDataWriter for atomically writing a
// KeyData to a LUKS2 token with the specicied name and priority on the specified
// LUKS2 container.
//
// The container must already contain a token of the correct type with the supplied
// name. The initial token is bootstrapped by InitializeLUKS2Container or
// SetLUKS2ContainerUnlockKey.
func NewLUKS2KeyDataWriter(devicePath, name string) (*LUKS2KeyDataWriter, error) {
view, err := newLUKSView(devicePath, luks2.LockModeBlocking)
if err != nil {
return nil, xerrors.Errorf("cannot obtain LUKS2 header view: %w", err)
}
token, id, exists := view.TokenByName(name)
if !exists {
return nil, errors.New("a keyslot with the specified name does not exist")
}
kdToken, ok := token.(*luksview.KeyDataToken)
if !ok {
return nil, errors.New("named keyslot has the wrong type")
}
return &LUKS2KeyDataWriter{
devicePath: devicePath,
id: id,
slot: token.Keyslots()[0],
name: name,
priority: kdToken.Priority,
Buffer: new(bytes.Buffer)}, nil
}
func (w *LUKS2KeyDataWriter) Commit() error {
token := &luksview.KeyDataToken{
TokenBase: luksview.TokenBase{
TokenKeyslot: w.slot,
TokenName: w.name},
Priority: w.priority,
Data: w.Bytes()}
return luks2ImportToken(w.devicePath, token, &luks2.ImportTokenOptions{Id: w.id, Replace: true})
}
// SetPriority sets the priority for the updated KeyData that is written using
// this writer. It must be called before Commit.
//
// Zero is the default priority, with higher numbers indicating a higher
// priority. A negative priority indicates that the KeyData shouldn't be used
// for activation unless referred to explicitly.
func (w *LUKS2KeyDataWriter) SetPriority(priority int) {
w.priority = priority
}