fd49993c3b
Change-Id: Ic3a91ccd2c8cdc364740f256fdb8a7ff66177947 Reviewed-on: https://boringssl-review.googlesource.com/14506 Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: Adam Langley <agl@google.com>
125 lines
3.5 KiB
Go
125 lines
3.5 KiB
Go
// Copyright (c) 2017, Google Inc.
|
|
//
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
// copyright notice and this permission notice appear in all copies.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
|
|
|
// inject-hash runs a binary compiled against a FIPS module that hasn't had the
|
|
// correct hash injected. That binary will fail the power-on integrity check
|
|
// and write the calcualted hash value to stderr. This script parses that and
|
|
// injects the calcualted value into the given object file.
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// uninitHashValue is the default hash value that we inject into the module.
|
|
// This value need only be distinct, i.e. so that we can safely
|
|
// search-and-replace it in an object file. This must match the value in bcm.c.
|
|
var uninitHashValue = [32]byte{
|
|
0x5f, 0x30, 0xd1, 0x80, 0xe7, 0x9e, 0x8f, 0x8f, 0xdf, 0x8b, 0x93, 0xd4, 0x96, 0x36, 0x30, 0xcc, 0x30, 0xea, 0x38, 0x0f, 0x75, 0x56, 0x9a, 0x1b, 0x23, 0x2f, 0x7c, 0x79, 0xff, 0x1b, 0x2b, 0xca,
|
|
}
|
|
|
|
func do(outPath, arInput, binPath string) error {
|
|
cmd := exec.Command(binPath)
|
|
out, err := cmd.CombinedOutput()
|
|
|
|
if err == nil {
|
|
return errors.New("binary did not fail self test")
|
|
}
|
|
|
|
lines := strings.Split(string(out), "\n")
|
|
if len(lines) < 3 {
|
|
return fmt.Errorf("too few lines in output: %q", out)
|
|
}
|
|
|
|
calculatedLine := lines[2]
|
|
if !strings.HasPrefix(calculatedLine, "Calculated: ") {
|
|
return errors.New("bad prefix of 3rd line: " + calculatedLine)
|
|
}
|
|
calculatedLine = calculatedLine[12:]
|
|
calculated, err := hex.DecodeString(calculatedLine)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(calculated) != len(uninitHashValue) {
|
|
return fmt.Errorf("unexpected length of calculated hash: got %d, want %d", len(calculated), len(uninitHashValue))
|
|
}
|
|
|
|
arFile, err := os.Open(arInput)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer arFile.Close()
|
|
|
|
ar := NewAR(arFile)
|
|
|
|
for {
|
|
header, err := ar.Next()
|
|
if err != nil {
|
|
return errors.New("error reading from archive file: " + err.Error())
|
|
}
|
|
|
|
if len(header.Name) > 0 {
|
|
break
|
|
}
|
|
|
|
if _, err := ioutil.ReadAll(ar); err != nil {
|
|
return errors.New("error reading from archive file: " + err.Error())
|
|
}
|
|
}
|
|
|
|
object, err := ioutil.ReadAll(ar)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
offset := bytes.Index(object, uninitHashValue[:])
|
|
if offset < 0 {
|
|
return errors.New("did not find uninitialised hash value in object file")
|
|
}
|
|
|
|
if bytes.Index(object[offset+1:], uninitHashValue[:]) >= 0 {
|
|
return errors.New("found two occurrences of uninitialised hash value in object file")
|
|
}
|
|
|
|
copy(object[offset:], calculated)
|
|
|
|
if err := ioutil.WriteFile(outPath, object, 0644); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
arInput := flag.String("in", "", "Path to a .a file")
|
|
outPath := flag.String("o", "", "Path to output object")
|
|
bin := flag.String("bin", "", "Binary compiled with the FIPS module")
|
|
|
|
flag.Parse()
|
|
|
|
if err := do(*outPath, *arInput, *bin); err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|