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  }