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