github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/gadget/install/encrypt_test.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_test 22 23 import ( 24 "errors" 25 "fmt" 26 "os" 27 28 . "gopkg.in/check.v1" 29 30 "github.com/snapcore/snapd/dirs" 31 "github.com/snapcore/snapd/gadget" 32 "github.com/snapcore/snapd/gadget/install" 33 "github.com/snapcore/snapd/secboot" 34 "github.com/snapcore/snapd/testutil" 35 ) 36 37 type encryptSuite struct { 38 testutil.BaseTest 39 40 mockCryptsetup *testutil.MockCmd 41 42 mockedEncryptionKey secboot.EncryptionKey 43 mockedRecoveryKey secboot.RecoveryKey 44 } 45 46 var _ = Suite(&encryptSuite{}) 47 48 var mockDeviceStructure = gadget.OnDiskStructure{ 49 LaidOutStructure: gadget.LaidOutStructure{ 50 VolumeStructure: &gadget.VolumeStructure{ 51 Name: "Test structure", 52 Size: 0x100000, 53 }, 54 StartOffset: 0, 55 Index: 1, 56 }, 57 Node: "/dev/node1", 58 } 59 60 func (s *encryptSuite) SetUpTest(c *C) { 61 dirs.SetRootDir(c.MkDir()) 62 c.Assert(os.MkdirAll(dirs.SnapRunDir, 0755), IsNil) 63 64 // create empty key to prevent blocking on lack of system entropy 65 s.mockedEncryptionKey = secboot.EncryptionKey{} 66 for i := range s.mockedEncryptionKey { 67 s.mockedEncryptionKey[i] = byte(i) 68 } 69 s.mockedRecoveryKey = secboot.RecoveryKey{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 70 } 71 72 func (s *encryptSuite) TestNewEncryptedDevice(c *C) { 73 for _, tc := range []struct { 74 mockedFormatErr error 75 mockedOpenErr string 76 expectedErr string 77 }{ 78 { 79 mockedFormatErr: nil, 80 mockedOpenErr: "", 81 expectedErr: "", 82 }, 83 { 84 mockedFormatErr: errors.New("format error"), 85 mockedOpenErr: "", 86 expectedErr: "cannot format encrypted device: format error", 87 }, 88 { 89 mockedFormatErr: nil, 90 mockedOpenErr: "open error", 91 expectedErr: "cannot open encrypted device on /dev/node1: open error", 92 }, 93 } { 94 script := "" 95 if tc.mockedOpenErr != "" { 96 script = fmt.Sprintf("echo '%s'>&2; exit 1", tc.mockedOpenErr) 97 98 } 99 s.mockCryptsetup = testutil.MockCommand(c, "cryptsetup", script) 100 s.AddCleanup(s.mockCryptsetup.Restore) 101 102 calls := 0 103 restore := install.MockSecbootFormatEncryptedDevice(func(key secboot.EncryptionKey, label, node string) error { 104 calls++ 105 c.Assert(key, DeepEquals, s.mockedEncryptionKey) 106 c.Assert(label, Equals, "some-label-enc") 107 c.Assert(node, Equals, "/dev/node1") 108 return tc.mockedFormatErr 109 }) 110 defer restore() 111 112 dev, err := install.NewEncryptedDevice(&mockDeviceStructure, s.mockedEncryptionKey, "some-label") 113 c.Assert(calls, Equals, 1) 114 if tc.expectedErr == "" { 115 c.Assert(err, IsNil) 116 } else { 117 c.Assert(err, ErrorMatches, tc.expectedErr) 118 continue 119 } 120 c.Assert(dev.Node, Equals, "/dev/mapper/some-label") 121 122 err = dev.Close() 123 c.Assert(err, IsNil) 124 125 c.Assert(s.mockCryptsetup.Calls(), DeepEquals, [][]string{ 126 {"cryptsetup", "open", "--key-file", "-", "/dev/node1", "some-label"}, 127 {"cryptsetup", "close", "some-label"}, 128 }) 129 } 130 } 131 132 func (s *encryptSuite) TestAddRecoveryKey(c *C) { 133 for _, tc := range []struct { 134 mockedAddErr error 135 expectedErr string 136 }{ 137 {mockedAddErr: nil, expectedErr: ""}, 138 {mockedAddErr: errors.New("add key error"), expectedErr: "add key error"}, 139 } { 140 s.mockCryptsetup = testutil.MockCommand(c, "cryptsetup", "") 141 s.AddCleanup(s.mockCryptsetup.Restore) 142 143 restore := install.MockSecbootFormatEncryptedDevice(func(key secboot.EncryptionKey, label, node string) error { 144 return nil 145 }) 146 defer restore() 147 148 calls := 0 149 restore = install.MockSecbootAddRecoveryKey(func(key secboot.EncryptionKey, rkey secboot.RecoveryKey, node string) error { 150 calls++ 151 c.Assert(key, DeepEquals, s.mockedEncryptionKey) 152 c.Assert(rkey, DeepEquals, s.mockedRecoveryKey) 153 c.Assert(node, Equals, "/dev/node1") 154 return tc.mockedAddErr 155 }) 156 defer restore() 157 158 dev, err := install.NewEncryptedDevice(&mockDeviceStructure, s.mockedEncryptionKey, "some-label") 159 c.Assert(err, IsNil) 160 161 err = dev.AddRecoveryKey(s.mockedEncryptionKey, s.mockedRecoveryKey) 162 c.Assert(calls, Equals, 1) 163 if tc.expectedErr == "" { 164 c.Assert(err, IsNil) 165 } else { 166 c.Assert(err, ErrorMatches, tc.expectedErr) 167 continue 168 } 169 170 err = dev.Close() 171 c.Assert(err, IsNil) 172 173 c.Assert(s.mockCryptsetup.Calls(), DeepEquals, [][]string{ 174 {"cryptsetup", "open", "--key-file", "-", "/dev/node1", "some-label"}, 175 {"cryptsetup", "close", "some-label"}, 176 }) 177 } 178 }