github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/exp/vboot/vboot.go (about) 1 // Copyright 2018 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 main 6 7 import ( 8 "crypto/sha1" 9 "crypto/sha256" 10 "flag" 11 "io/ioutil" 12 "log" 13 "os" 14 "os/exec" 15 "syscall" 16 17 "github.com/google/go-tpm/tpm" 18 "golang.org/x/crypto/ed25519" 19 ) 20 21 const ( 22 tpmDevice string = "/dev/tpm0" 23 mountPath string = "/mnt/vboot" 24 filesystem string = "ext3" 25 ) 26 27 var ( 28 publicKey = flag.String("pubkey", "/etc/sig.pub", "A public key which should verify the signature.") 29 pcr = flag.Uint("pcr", 12, "The pcr index used for measuring the kernel before kexec.") 30 bootDev = flag.String("boot-device", "/dev/sda1", "The boot device which is used to kexec into a signed kernel.") 31 linuxKernel = flag.String("kernel", "/mnt/vboot/kernel", "Kernel image file path.") 32 linuxKernelSignature = flag.String("kernel-sig", "/mnt/vboot/kernel.sig", "Kernel image signature file path.") 33 initrd = flag.String("initrd", "/mnt/vboot/initrd", "Initrd file path.") 34 initrdSignature = flag.String("initrd-sig", "/mnt/vboot/initrd.sig", "Initrd signature file path.") 35 debug = flag.Bool("debug", false, "Enables debug mode.") 36 noTPM = flag.Bool("no-tpm", false, "Disables tpm measuring process.") 37 ) 38 39 func die(err error) { 40 if *debug { 41 panic(err) 42 } 43 if err := syscall.Reboot(syscall.LINUX_REBOOT_CMD_POWER_OFF); err != nil { 44 log.Fatalf("reboot err: %v", err) 45 } 46 } 47 48 func main() { 49 flag.Parse() 50 51 if err := os.MkdirAll(mountPath, os.ModePerm); err != nil { 52 die(err) 53 } 54 55 if err := syscall.Mount(*bootDev, mountPath, filesystem, syscall.MS_RDONLY, ""); err != nil { 56 die(err) 57 } 58 59 paths := []string{*publicKey, *linuxKernel, *linuxKernelSignature, *initrd, *initrdSignature} 60 files := make(map[string][]byte) 61 62 for _, element := range paths { 63 data, err := ioutil.ReadFile(element) 64 if err != nil { 65 die(err) 66 } else { 67 files[element] = data 68 } 69 } 70 71 kernelDigest := sha256.Sum256(files[*linuxKernel]) 72 initrdDigest := sha256.Sum256(files[*initrd]) 73 74 pcrDigestKernel := sha1.Sum(files[*linuxKernel]) 75 pcrDigestInitrd := sha1.Sum(files[*initrd]) 76 77 kernelSuccess := ed25519.Verify(files[*publicKey], kernelDigest[:], files[*linuxKernelSignature]) 78 initrdSuccess := ed25519.Verify(files[*publicKey], initrdDigest[:], files[*initrdSignature]) 79 80 if !kernelSuccess || !initrdSuccess { 81 die(nil) 82 } 83 84 if !*noTPM { 85 rwc, err := tpm.OpenTPM(tpmDevice) 86 if err != nil { 87 die(err) 88 } 89 90 tpm.PcrExtend(rwc, uint32(*pcr), pcrDigestKernel) 91 tpm.PcrExtend(rwc, uint32(*pcr), pcrDigestInitrd) 92 } 93 94 binary, lookErr := exec.LookPath("kexec") 95 if lookErr != nil { 96 die(lookErr) 97 } 98 99 args := []string{"kexec", "-initrd", *initrd, *linuxKernel} 100 env := os.Environ() 101 102 if execErr := syscall.Exec(binary, args, env); execErr != nil { 103 die(execErr) 104 } 105 }