-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathluks.go
More file actions
133 lines (121 loc) · 4.05 KB
/
Copy pathluks.go
File metadata and controls
133 lines (121 loc) · 4.05 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
package luks
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"github.com/anatol/devmapper.go"
)
// ErrPassphraseDoesNotMatch is an error that indicates provided passphrase does not match
var ErrPassphraseDoesNotMatch = errors.New("passphrase does not match")
// Device represents LUKS partition data
type Device interface {
io.Closer
// Version returns version of LUKS disk
Version() int
// Path returns block device path
Path() string
// UUID returns UUID of the LUKS partition
UUID() string
// Slots returns list of all active slots for this device sorted by priority
Slots() []int
// Tokens returns list of available tokens (metadata) for slots
Tokens() ([]Token, error)
// FlagsGet get the list of LUKS flags (options) used during unlocking
FlagsGet() []string
// FlagsAdd adds LUKS flags used for the upcoming unlocking
// Note that this method does not update LUKS v2 persistent flags
FlagsAdd(flags ...string) error
// FlagsClear clears flags
// Note that this method does not update LUKS v2 persistent flags
FlagsClear()
// UnsealVolume recovers slot password and then populates Volume structure that contains information needed to
// create a mapper device
UnsealVolume(keyslot int, passphrase []byte) (*Volume, error)
// Unlock is a shortcut for
// ```go
// volume, err := dev.UnsealVolume(keyslot, passphrase)
// volume.SetupMapper(dmName)
// ```
Unlock(keyslot int, passphrase []byte, dmName string) error
// UnlockAny iterates over all available slots and tries to unlock them until succeeds
UnlockAny(passphrase []byte, dmName string) error
}
// List of options handled by luks.go API.
// These names correspond to LUKSv2 persistent flags names (see persistent_flags[] array).
const (
FlagAllowDiscards string = "allow-discards"
FlagSameCPUCrypt string = "same-cpu-crypt"
FlagSubmitFromCryptCPUs string = "submit-from-crypt-cpus"
FlagNoReadWorkqueue string = "no-read-workqueue" // supported at Linux 5.9 or newer
FlagNoWriteWorkqueue string = "no-write-workqueue" // supported at Linux 5.9 or newer
)
// Token represents LUKS token metadata information
type Token struct {
ID int
Slots []int
// Type of the token e.g. "clevis", "systemd-fido2"
Type string
Payload []byte
}
// openFromFiles detects the LUKS version from hdrF, verifies the magic bytes,
// and dispatches to the appropriate init function.
func openFromFiles(devicePath string, hdrF, dataF *os.File) (Device, error) {
// LUKS magic and version occupy the first 8 bytes of the header:
// bytes 0-5: magic "LUKS\xba\xbe" (standard LUKS signature)
// bytes 6-7: version number in big-endian
header := make([]byte, 8)
if _, err := hdrF.ReadAt(header, 0); err != nil {
return nil, err
}
if !bytes.Equal(header[0:6], []byte("LUKS\xba\xbe")) {
return nil, fmt.Errorf("invalid LUKS header")
}
version := int(header[6])<<8 + int(header[7]) // big-endian uint16
switch version {
case 1:
return initV1Device(devicePath, hdrF, dataF)
case 2:
return initV2Device(devicePath, hdrF, dataF)
default:
return nil, fmt.Errorf("invalid LUKS version %d", version)
}
}
// Open reads LUKS headers from the given partition and returns LUKS device object.
// This function internally handles LUKS v1 and v2 partitions metadata.
func Open(path string) (Device, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
dev, err := openFromFiles(path, f, f)
if err != nil {
f.Close()
}
return dev, err
}
// OpenWithHeader opens a LUKS device that uses a detached header.
// The LUKS metadata and keyslot material are read from headerPath,
// while the encrypted data resides on devicePath.
func OpenWithHeader(devicePath, headerPath string) (Device, error) {
hdrF, err := os.Open(headerPath)
if err != nil {
return nil, err
}
dataF, err := os.Open(devicePath)
if err != nil {
hdrF.Close()
return nil, err
}
dev, err := openFromFiles(devicePath, hdrF, dataF)
if err != nil {
hdrF.Close()
dataF.Close()
}
return dev, err
}
// Lock closes device mapper partition with the given name
func Lock(name string) error {
return devmapper.Remove(name)
}