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 }