github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/gadget/install/encrypt_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2020 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package install_test
    21  
    22  import (
    23  	"errors"
    24  	"fmt"
    25  	"os"
    26  
    27  	. "gopkg.in/check.v1"
    28  
    29  	"github.com/snapcore/snapd/dirs"
    30  	"github.com/snapcore/snapd/gadget"
    31  	"github.com/snapcore/snapd/gadget/install"
    32  	"github.com/snapcore/snapd/secboot"
    33  	"github.com/snapcore/snapd/testutil"
    34  )
    35  
    36  type encryptSuite struct {
    37  	testutil.BaseTest
    38  
    39  	mockCryptsetup *testutil.MockCmd
    40  
    41  	mockedEncryptionKey secboot.EncryptionKey
    42  	mockedRecoveryKey   secboot.RecoveryKey
    43  }
    44  
    45  var _ = Suite(&encryptSuite{})
    46  
    47  var mockDeviceStructure = gadget.OnDiskStructure{
    48  	LaidOutStructure: gadget.LaidOutStructure{
    49  		VolumeStructure: &gadget.VolumeStructure{
    50  			Name: "Test structure",
    51  			Size: 0x100000,
    52  		},
    53  		StartOffset: 0,
    54  		Index:       1,
    55  	},
    56  	Node: "/dev/node1",
    57  }
    58  
    59  func (s *encryptSuite) SetUpTest(c *C) {
    60  	dirs.SetRootDir(c.MkDir())
    61  	c.Assert(os.MkdirAll(dirs.SnapRunDir, 0755), IsNil)
    62  
    63  	// create empty key to prevent blocking on lack of system entropy
    64  	s.mockedEncryptionKey = secboot.EncryptionKey{}
    65  	for i := range s.mockedEncryptionKey {
    66  		s.mockedEncryptionKey[i] = byte(i)
    67  	}
    68  	s.mockedRecoveryKey = secboot.RecoveryKey{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
    69  }
    70  
    71  func (s *encryptSuite) TestNewEncryptedDevice(c *C) {
    72  	for _, tc := range []struct {
    73  		mockedFormatErr error
    74  		mockedOpenErr   string
    75  		expectedErr     string
    76  	}{
    77  		{
    78  			mockedFormatErr: nil,
    79  			mockedOpenErr:   "",
    80  			expectedErr:     "",
    81  		},
    82  		{
    83  			mockedFormatErr: errors.New("format error"),
    84  			mockedOpenErr:   "",
    85  			expectedErr:     "cannot format encrypted device: format error",
    86  		},
    87  		{
    88  			mockedFormatErr: nil,
    89  			mockedOpenErr:   "open error",
    90  			expectedErr:     "cannot open encrypted device on /dev/node1: open error",
    91  		},
    92  	} {
    93  		script := ""
    94  		if tc.mockedOpenErr != "" {
    95  			script = fmt.Sprintf("echo '%s'>&2; exit 1", tc.mockedOpenErr)
    96  
    97  		}
    98  		s.mockCryptsetup = testutil.MockCommand(c, "cryptsetup", script)
    99  		s.AddCleanup(s.mockCryptsetup.Restore)
   100  
   101  		calls := 0
   102  		restore := install.MockSecbootFormatEncryptedDevice(func(key secboot.EncryptionKey, label, node string) error {
   103  			calls++
   104  			c.Assert(key, DeepEquals, s.mockedEncryptionKey)
   105  			c.Assert(label, Equals, "some-label-enc")
   106  			c.Assert(node, Equals, "/dev/node1")
   107  			return tc.mockedFormatErr
   108  		})
   109  		defer restore()
   110  
   111  		dev, err := install.NewEncryptedDevice(&mockDeviceStructure, s.mockedEncryptionKey, "some-label")
   112  		c.Assert(calls, Equals, 1)
   113  		if tc.expectedErr == "" {
   114  			c.Assert(err, IsNil)
   115  		} else {
   116  			c.Assert(err, ErrorMatches, tc.expectedErr)
   117  			continue
   118  		}
   119  		c.Assert(dev.Node, Equals, "/dev/mapper/some-label")
   120  
   121  		err = dev.Close()
   122  		c.Assert(err, IsNil)
   123  
   124  		c.Assert(s.mockCryptsetup.Calls(), DeepEquals, [][]string{
   125  			{"cryptsetup", "open", "--key-file", "-", "/dev/node1", "some-label"},
   126  			{"cryptsetup", "close", "some-label"},
   127  		})
   128  	}
   129  }
   130  
   131  func (s *encryptSuite) TestAddRecoveryKey(c *C) {
   132  	for _, tc := range []struct {
   133  		mockedAddErr error
   134  		expectedErr  string
   135  	}{
   136  		{mockedAddErr: nil, expectedErr: ""},
   137  		{mockedAddErr: errors.New("add key error"), expectedErr: "add key error"},
   138  	} {
   139  		s.mockCryptsetup = testutil.MockCommand(c, "cryptsetup", "")
   140  		s.AddCleanup(s.mockCryptsetup.Restore)
   141  
   142  		restore := install.MockSecbootFormatEncryptedDevice(func(key secboot.EncryptionKey, label, node string) error {
   143  			return nil
   144  		})
   145  		defer restore()
   146  
   147  		calls := 0
   148  		restore = install.MockSecbootAddRecoveryKey(func(key secboot.EncryptionKey, rkey secboot.RecoveryKey, node string) error {
   149  			calls++
   150  			c.Assert(key, DeepEquals, s.mockedEncryptionKey)
   151  			c.Assert(rkey, DeepEquals, s.mockedRecoveryKey)
   152  			c.Assert(node, Equals, "/dev/node1")
   153  			return tc.mockedAddErr
   154  		})
   155  		defer restore()
   156  
   157  		dev, err := install.NewEncryptedDevice(&mockDeviceStructure, s.mockedEncryptionKey, "some-label")
   158  		c.Assert(err, IsNil)
   159  
   160  		err = dev.AddRecoveryKey(s.mockedEncryptionKey, s.mockedRecoveryKey)
   161  		c.Assert(calls, Equals, 1)
   162  		if tc.expectedErr == "" {
   163  			c.Assert(err, IsNil)
   164  		} else {
   165  			c.Assert(err, ErrorMatches, tc.expectedErr)
   166  			continue
   167  		}
   168  
   169  		err = dev.Close()
   170  		c.Assert(err, IsNil)
   171  
   172  		c.Assert(s.mockCryptsetup.Calls(), DeepEquals, [][]string{
   173  			{"cryptsetup", "open", "--key-file", "-", "/dev/node1", "some-label"},
   174  			{"cryptsetup", "close", "some-label"},
   175  		})
   176  	}
   177  }