gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/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 "os/exec" 27 28 "github.com/snapcore/snapd/gadget" 29 "github.com/snapcore/snapd/osutil" 30 "github.com/snapcore/snapd/secboot" 31 ) 32 33 var ( 34 secbootFormatEncryptedDevice = secboot.FormatEncryptedDevice 35 secbootAddRecoveryKey = secboot.AddRecoveryKey 36 ) 37 38 // encryptedDevice represents a LUKS-backed encrypted block device. 39 type encryptedDevice struct { 40 parent *gadget.OnDiskStructure 41 name string 42 Node string 43 } 44 45 // newEncryptedDevice creates an encrypted device in the existing partition using the 46 // specified key. 47 func newEncryptedDevice(part *gadget.OnDiskStructure, key secboot.EncryptionKey, name string) (*encryptedDevice, error) { 48 dev := &encryptedDevice{ 49 parent: part, 50 name: name, 51 // A new block device is used to access the encrypted data. Note that 52 // you can't open an encrypted device under different names and a name 53 // can't be used in more than one device at the same time. 54 Node: fmt.Sprintf("/dev/mapper/%s", name), 55 } 56 57 if err := secbootFormatEncryptedDevice(key, name+"-enc", part.Node); err != nil { 58 return nil, fmt.Errorf("cannot format encrypted device: %v", err) 59 } 60 61 if err := cryptsetupOpen(key, part.Node, name); err != nil { 62 return nil, fmt.Errorf("cannot open encrypted device on %s: %s", part.Node, err) 63 } 64 65 return dev, nil 66 } 67 68 func (dev *encryptedDevice) AddRecoveryKey(key secboot.EncryptionKey, rkey secboot.RecoveryKey) error { 69 return secbootAddRecoveryKey(key, rkey, dev.parent.Node) 70 } 71 72 func (dev *encryptedDevice) Close() error { 73 return cryptsetupClose(dev.name) 74 } 75 76 func cryptsetupOpen(key secboot.EncryptionKey, node, name string) error { 77 cmd := exec.Command("cryptsetup", "open", "--key-file", "-", node, name) 78 cmd.Stdin = bytes.NewReader(key[:]) 79 if output, err := cmd.CombinedOutput(); err != nil { 80 return osutil.OutputErr(output, err) 81 } 82 return nil 83 } 84 85 func cryptsetupClose(name string) error { 86 if output, err := exec.Command("cryptsetup", "close", name).CombinedOutput(); err != nil { 87 return osutil.OutputErr(output, err) 88 } 89 return nil 90 }