github.com/chipaca/snappy@v0.0.0-20210104084008-1f06296fe8ad/secboot/encrypt.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 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 = 64 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 43 // EncryptionKey is the key used to encrypt the data partition. 44 type EncryptionKey [encryptionKeySize]byte 45 46 func NewEncryptionKey() (EncryptionKey, error) { 47 var key EncryptionKey 48 // rand.Read() is protected against short reads 49 _, err := rand.Read(key[:]) 50 // On return, n == len(b) if and only if err == nil 51 return key, err 52 } 53 54 // Save writes the key in the location specified by filename. 55 func (key EncryptionKey) Save(filename string) error { 56 if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil { 57 return err 58 } 59 return osutil.AtomicWriteFile(filename, key[:], 0600, 0) 60 } 61 62 // RecoveryKey is a key used to unlock the encrypted partition when 63 // the encryption key can't be used, for example when unseal fails. 64 type RecoveryKey [recoveryKeySize]byte 65 66 func NewRecoveryKey() (RecoveryKey, error) { 67 var key RecoveryKey 68 // rand.Read() is protected against short reads 69 _, err := rand.Read(key[:]) 70 // On return, n == len(b) if and only if err == nil 71 return key, err 72 } 73 74 // Save writes the recovery key in the location specified by filename. 75 func (key RecoveryKey) Save(filename string) error { 76 if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil { 77 return err 78 } 79 return osutil.AtomicWriteFile(filename, key[:], 0600, 0) 80 } 81 82 func RecoveryKeyFromFile(recoveryKeyFile string) (*RecoveryKey, error) { 83 f, err := os.Open(recoveryKeyFile) 84 if err != nil { 85 return nil, fmt.Errorf("cannot open recovery key: %v", err) 86 } 87 defer f.Close() 88 st, err := f.Stat() 89 if err != nil { 90 return nil, fmt.Errorf("cannot stat recovery key: %v", err) 91 } 92 if st.Size() != int64(len(RecoveryKey{})) { 93 return nil, fmt.Errorf("cannot read recovery key: unexpected size %v for the recovery key file %s", st.Size(), recoveryKeyFile) 94 } 95 96 var rkey RecoveryKey 97 if _, err := io.ReadFull(f, rkey[:]); err != nil { 98 return nil, fmt.Errorf("cannot read recovery key: %v", err) 99 } 100 return &rkey, nil 101 }