github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/pkg/securelaunch/measurement/files.go (about) 1 // Copyright 2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package measurement 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "log" 14 15 "github.com/u-root/u-root/pkg/mount" 16 slaunch "github.com/u-root/u-root/pkg/securelaunch" 17 "github.com/u-root/u-root/pkg/securelaunch/tpm" 18 ) 19 20 /* describes the "files" portion of policy file */ 21 type FileCollector struct { 22 Type string `json:"type"` 23 Paths []string `json:"paths"` 24 } 25 26 /* 27 * NewFileCollector extracts the "files" portion from the policy file. 28 * initializes a new FileCollector structure. 29 * returns error if unmarshalling of FileCollector fails 30 */ 31 func NewFileCollector(config []byte) (Collector, error) { 32 slaunch.Debug("New Files Collector initialized\n") 33 var fc = new(FileCollector) 34 err := json.Unmarshal(config, &fc) 35 if err != nil { 36 return nil, err 37 } 38 return fc, nil 39 } 40 41 /* 42 * HashFile reads file input by user and calls TPM to measure it and store the hash. 43 * 44 * inputVal is of format <block device identifier>:<path> 45 * E.g sda:/path/to/file _OR UUID:/path/to/file 46 * Performs following actions 47 * 1. mount device 48 * 2. Read file on device into a byte slice. 49 * 3. Unmount device 50 * 4. Call tpm package which measures byte slice and stores it. 51 */ 52 func HashFile(tpmHandle io.ReadWriteCloser, inputVal string) error { 53 // inputVal is of type sda:path 54 mntFilePath, mountPath, e := slaunch.GetMountedFilePath(inputVal, mount.MS_RDONLY) 55 if e != nil { 56 log.Printf("HashFile: GetMountedFilePath err=%v", e) 57 return fmt.Errorf("failed to get mount path, err=%v", e) 58 } 59 slaunch.Debug("File Collector: Reading file=%s", mntFilePath) 60 61 slaunch.Debug("File Collector: fileP=%s, mountP=%s\n", mntFilePath, mountPath) 62 d, err := ioutil.ReadFile(mntFilePath) 63 if e := mount.Unmount(mountPath, true, false); e != nil { 64 log.Printf("File Collector: Unmount failed. PANIC\n") 65 panic(e) 66 } 67 68 if err != nil { 69 return fmt.Errorf("failed to read target file: filePath=%s, mountPath=%s, inputVal=%s, err=%v", 70 mntFilePath, mountPath, inputVal, err) 71 } 72 73 return tpm.ExtendPCRDebug(tpmHandle, pcr, bytes.NewReader(d)) 74 } 75 76 /* 77 * Collect satisfies Collector Interface. It loops over all file paths provided by user 78 * and for each file path, calls HashFile. HashFile measures each file on 79 * that path and stores the result in TPM. 80 */ 81 func (s *FileCollector) Collect(tpmHandle io.ReadWriteCloser) error { 82 83 for _, inputVal := range s.Paths { 84 // inputVal is of type sda:/path/to/file 85 err := HashFile(tpmHandle, inputVal) 86 if err != nil { 87 log.Printf("File Collector: input=%s, err = %v", inputVal, err) 88 return err 89 } 90 } 91 92 return nil 93 }