github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/gadget/install/encrypt.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 // +build !nosecboot 3 4 /* 5 * Copyright (C) 2020 Canonical Ltd 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 3 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 package install 22 23 import ( 24 "bytes" 25 "fmt" 26 "io/ioutil" 27 "os/exec" 28 29 "github.com/snapcore/snapd/gadget" 30 "github.com/snapcore/snapd/osutil" 31 "github.com/snapcore/snapd/secboot" 32 ) 33 34 var ( 35 tempFile = ioutil.TempFile 36 ) 37 38 var ( 39 secbootFormatEncryptedDevice = secboot.FormatEncryptedDevice 40 secbootAddRecoveryKey = secboot.AddRecoveryKey 41 ) 42 43 // encryptedDevice represents a LUKS-backed encrypted block device. 44 type encryptedDevice struct { 45 parent *gadget.OnDiskStructure 46 name string 47 Node string 48 } 49 50 // newEncryptedDevice creates an encrypted device in the existing partition using the 51 // specified key. 52 func newEncryptedDevice(part *gadget.OnDiskStructure, key secboot.EncryptionKey, name string) (*encryptedDevice, error) { 53 dev := &encryptedDevice{ 54 parent: part, 55 name: name, 56 // A new block device is used to access the encrypted data. Note that 57 // you can't open an encrypted device under different names and a name 58 // can't be used in more than one device at the same time. 59 Node: fmt.Sprintf("/dev/mapper/%s", name), 60 } 61 62 if err := secbootFormatEncryptedDevice(key, name+"-enc", part.Node); err != nil { 63 return nil, fmt.Errorf("cannot format encrypted device: %v", err) 64 } 65 66 if err := cryptsetupOpen(key, part.Node, name); err != nil { 67 return nil, fmt.Errorf("cannot open encrypted device on %s: %s", part.Node, err) 68 } 69 70 return dev, nil 71 } 72 73 func (dev *encryptedDevice) AddRecoveryKey(key secboot.EncryptionKey, rkey secboot.RecoveryKey) error { 74 return secbootAddRecoveryKey(key, rkey, dev.parent.Node) 75 } 76 77 func (dev *encryptedDevice) Close() error { 78 return cryptsetupClose(dev.name) 79 } 80 81 func cryptsetupOpen(key secboot.EncryptionKey, node, name string) error { 82 cmd := exec.Command("cryptsetup", "open", "--key-file", "-", node, name) 83 cmd.Stdin = bytes.NewReader(key[:]) 84 if output, err := cmd.CombinedOutput(); err != nil { 85 return osutil.OutputErr(output, err) 86 } 87 return nil 88 } 89 90 func cryptsetupClose(name string) error { 91 if output, err := exec.Command("cryptsetup", "close", name).CombinedOutput(); err != nil { 92 return osutil.OutputErr(output, err) 93 } 94 return nil 95 }