github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/secboot/encrypt.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2021 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 secboot 21 22 import ( 23 "crypto/rand" 24 "fmt" 25 "io" 26 "os" 27 "path/filepath" 28 29 "github.com/snapcore/snapd/osutil" 30 ) 31 32 const ( 33 // The encryption key size is set so it has the same entropy as the derived 34 // key. 35 encryptionKeySize = 32 36 37 // XXX: needs to be in sync with 38 // github.com/snapcore/secboot/crypto.go:"type RecoveryKey" 39 // Size of the recovery key. 40 recoveryKeySize = 16 41 42 // The auxiliary key is used to bind keys to models 43 auxKeySize = 32 44 ) 45 46 // used in tests 47 var randRead = rand.Read 48 49 // EncryptionKey is the key used to encrypt the data partition. 50 type EncryptionKey []byte 51 52 func NewEncryptionKey() (EncryptionKey, error) { 53 key := make(EncryptionKey, encryptionKeySize) 54 // rand.Read() is protected against short reads 55 _, err := randRead(key[:]) 56 // On return, n == len(b) if and only if err == nil 57 return key, err 58 } 59 60 // Save writes the key in the location specified by filename. 61 func (key EncryptionKey) Save(filename string) error { 62 if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil { 63 return err 64 } 65 return osutil.AtomicWriteFile(filename, key[:], 0600, 0) 66 } 67 68 // RecoveryKey is a key used to unlock the encrypted partition when 69 // the encryption key can't be used, for example when unseal fails. 70 type RecoveryKey [recoveryKeySize]byte 71 72 func NewRecoveryKey() (RecoveryKey, error) { 73 var key RecoveryKey 74 // rand.Read() is protected against short reads 75 _, err := randRead(key[:]) 76 // On return, n == len(b) if and only if err == nil 77 return key, err 78 } 79 80 // Save writes the recovery key in the location specified by filename. 81 func (key RecoveryKey) Save(filename string) error { 82 if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil { 83 return err 84 } 85 return osutil.AtomicWriteFile(filename, key[:], 0600, 0) 86 } 87 88 func RecoveryKeyFromFile(recoveryKeyFile string) (*RecoveryKey, error) { 89 f, err := os.Open(recoveryKeyFile) 90 if err != nil { 91 return nil, fmt.Errorf("cannot open recovery key: %v", err) 92 } 93 defer f.Close() 94 st, err := f.Stat() 95 if err != nil { 96 return nil, fmt.Errorf("cannot stat recovery key: %v", err) 97 } 98 if st.Size() != int64(len(RecoveryKey{})) { 99 return nil, fmt.Errorf("cannot read recovery key: unexpected size %v for the recovery key file %s", st.Size(), recoveryKeyFile) 100 } 101 102 var rkey RecoveryKey 103 if _, err := io.ReadFull(f, rkey[:]); err != nil { 104 return nil, fmt.Errorf("cannot read recovery key: %v", err) 105 } 106 return &rkey, nil 107 } 108 109 // AuxKey is the key to bind models to keys. 110 type AuxKey [auxKeySize]byte 111 112 func NewAuxKey() (AuxKey, error) { 113 var key AuxKey 114 // rand.Read() is protected against short reads 115 _, err := randRead(key[:]) 116 // On return, n == len(b) if and only if err == nil 117 return key, err 118 }