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