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  }