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  }