xref: /aosp_15_r20/external/boringssl/src/util/fipstools/break-hash.go (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1*8fb009dcSAndroid Build Coastguard Worker// Copyright (c) 2017, Google Inc.
2*8fb009dcSAndroid Build Coastguard Worker//
3*8fb009dcSAndroid Build Coastguard Worker// Permission to use, copy, modify, and/or distribute this software for any
4*8fb009dcSAndroid Build Coastguard Worker// purpose with or without fee is hereby granted, provided that the above
5*8fb009dcSAndroid Build Coastguard Worker// copyright notice and this permission notice appear in all copies.
6*8fb009dcSAndroid Build Coastguard Worker//
7*8fb009dcSAndroid Build Coastguard Worker// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*8fb009dcSAndroid Build Coastguard Worker// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*8fb009dcSAndroid Build Coastguard Worker// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10*8fb009dcSAndroid Build Coastguard Worker// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*8fb009dcSAndroid Build Coastguard Worker// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12*8fb009dcSAndroid Build Coastguard Worker// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13*8fb009dcSAndroid Build Coastguard Worker// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14*8fb009dcSAndroid Build Coastguard Worker
15*8fb009dcSAndroid Build Coastguard Worker//go:build ignore
16*8fb009dcSAndroid Build Coastguard Worker
17*8fb009dcSAndroid Build Coastguard Worker// break-hash parses an ELF binary containing the FIPS module and corrupts the
18*8fb009dcSAndroid Build Coastguard Worker// first byte of the module. This should cause the integrity check to fail.
19*8fb009dcSAndroid Build Coastguard Workerpackage main
20*8fb009dcSAndroid Build Coastguard Worker
21*8fb009dcSAndroid Build Coastguard Workerimport (
22*8fb009dcSAndroid Build Coastguard Worker	"bytes"
23*8fb009dcSAndroid Build Coastguard Worker	"crypto/hmac"
24*8fb009dcSAndroid Build Coastguard Worker	"crypto/sha512"
25*8fb009dcSAndroid Build Coastguard Worker	"debug/elf"
26*8fb009dcSAndroid Build Coastguard Worker	"encoding/hex"
27*8fb009dcSAndroid Build Coastguard Worker	"errors"
28*8fb009dcSAndroid Build Coastguard Worker	"fmt"
29*8fb009dcSAndroid Build Coastguard Worker	"os"
30*8fb009dcSAndroid Build Coastguard Worker)
31*8fb009dcSAndroid Build Coastguard Worker
32*8fb009dcSAndroid Build Coastguard Workerfunc do(outPath, inPath string) error {
33*8fb009dcSAndroid Build Coastguard Worker	objectBytes, err := os.ReadFile(inPath)
34*8fb009dcSAndroid Build Coastguard Worker	if err != nil {
35*8fb009dcSAndroid Build Coastguard Worker		return err
36*8fb009dcSAndroid Build Coastguard Worker	}
37*8fb009dcSAndroid Build Coastguard Worker
38*8fb009dcSAndroid Build Coastguard Worker	object, err := elf.NewFile(bytes.NewReader(objectBytes))
39*8fb009dcSAndroid Build Coastguard Worker	if err != nil {
40*8fb009dcSAndroid Build Coastguard Worker		return errors.New("failed to parse object: " + err.Error())
41*8fb009dcSAndroid Build Coastguard Worker	}
42*8fb009dcSAndroid Build Coastguard Worker
43*8fb009dcSAndroid Build Coastguard Worker	// Find the .text section.
44*8fb009dcSAndroid Build Coastguard Worker	var textSection *elf.Section
45*8fb009dcSAndroid Build Coastguard Worker	var textSectionIndex elf.SectionIndex
46*8fb009dcSAndroid Build Coastguard Worker	for i, section := range object.Sections {
47*8fb009dcSAndroid Build Coastguard Worker		if section.Name == ".text" {
48*8fb009dcSAndroid Build Coastguard Worker			textSectionIndex = elf.SectionIndex(i)
49*8fb009dcSAndroid Build Coastguard Worker			textSection = section
50*8fb009dcSAndroid Build Coastguard Worker			break
51*8fb009dcSAndroid Build Coastguard Worker		}
52*8fb009dcSAndroid Build Coastguard Worker	}
53*8fb009dcSAndroid Build Coastguard Worker
54*8fb009dcSAndroid Build Coastguard Worker	if textSection == nil {
55*8fb009dcSAndroid Build Coastguard Worker		return errors.New("failed to find .text section in object")
56*8fb009dcSAndroid Build Coastguard Worker	}
57*8fb009dcSAndroid Build Coastguard Worker
58*8fb009dcSAndroid Build Coastguard Worker	symbols, err := object.Symbols()
59*8fb009dcSAndroid Build Coastguard Worker	if err != nil {
60*8fb009dcSAndroid Build Coastguard Worker		fmt.Fprintf(os.Stderr, "%s\nTrying dynamic symbols\n", err)
61*8fb009dcSAndroid Build Coastguard Worker		symbols, err = object.DynamicSymbols()
62*8fb009dcSAndroid Build Coastguard Worker	}
63*8fb009dcSAndroid Build Coastguard Worker	if err != nil {
64*8fb009dcSAndroid Build Coastguard Worker		return errors.New("failed to parse symbols: " + err.Error())
65*8fb009dcSAndroid Build Coastguard Worker	}
66*8fb009dcSAndroid Build Coastguard Worker
67*8fb009dcSAndroid Build Coastguard Worker	// Find the start and end markers of the module.
68*8fb009dcSAndroid Build Coastguard Worker	var startSeen, endSeen bool
69*8fb009dcSAndroid Build Coastguard Worker	var start, end uint64
70*8fb009dcSAndroid Build Coastguard Worker
71*8fb009dcSAndroid Build Coastguard Worker	for _, symbol := range symbols {
72*8fb009dcSAndroid Build Coastguard Worker		if symbol.Section != textSectionIndex {
73*8fb009dcSAndroid Build Coastguard Worker			continue
74*8fb009dcSAndroid Build Coastguard Worker		}
75*8fb009dcSAndroid Build Coastguard Worker
76*8fb009dcSAndroid Build Coastguard Worker		switch symbol.Name {
77*8fb009dcSAndroid Build Coastguard Worker		case "BORINGSSL_bcm_text_start":
78*8fb009dcSAndroid Build Coastguard Worker			if startSeen {
79*8fb009dcSAndroid Build Coastguard Worker				return errors.New("duplicate start symbol found")
80*8fb009dcSAndroid Build Coastguard Worker			}
81*8fb009dcSAndroid Build Coastguard Worker			startSeen = true
82*8fb009dcSAndroid Build Coastguard Worker			start = symbol.Value
83*8fb009dcSAndroid Build Coastguard Worker		case "BORINGSSL_bcm_text_end":
84*8fb009dcSAndroid Build Coastguard Worker			if endSeen {
85*8fb009dcSAndroid Build Coastguard Worker				return errors.New("duplicate end symbol found")
86*8fb009dcSAndroid Build Coastguard Worker			}
87*8fb009dcSAndroid Build Coastguard Worker			endSeen = true
88*8fb009dcSAndroid Build Coastguard Worker			end = symbol.Value
89*8fb009dcSAndroid Build Coastguard Worker		default:
90*8fb009dcSAndroid Build Coastguard Worker			continue
91*8fb009dcSAndroid Build Coastguard Worker		}
92*8fb009dcSAndroid Build Coastguard Worker	}
93*8fb009dcSAndroid Build Coastguard Worker
94*8fb009dcSAndroid Build Coastguard Worker	if !startSeen || !endSeen {
95*8fb009dcSAndroid Build Coastguard Worker		return errors.New("could not find module in object")
96*8fb009dcSAndroid Build Coastguard Worker	}
97*8fb009dcSAndroid Build Coastguard Worker
98*8fb009dcSAndroid Build Coastguard Worker	moduleText := make([]byte, end-start)
99*8fb009dcSAndroid Build Coastguard Worker	if n, err := textSection.ReadAt(moduleText, int64(start-textSection.Addr)); err != nil {
100*8fb009dcSAndroid Build Coastguard Worker		return fmt.Errorf("failed to read from module start (at %d of %d) in .text: %s", start, textSection.Size, err)
101*8fb009dcSAndroid Build Coastguard Worker	} else if n != len(moduleText) {
102*8fb009dcSAndroid Build Coastguard Worker		return fmt.Errorf("short read from .text: wanted %d, got %d", len(moduleText), n)
103*8fb009dcSAndroid Build Coastguard Worker	}
104*8fb009dcSAndroid Build Coastguard Worker
105*8fb009dcSAndroid Build Coastguard Worker	// In order to match up the module start with the raw ELF contents,
106*8fb009dcSAndroid Build Coastguard Worker	// search for the first 256 bytes and assume that will be unique.
107*8fb009dcSAndroid Build Coastguard Worker	offset := bytes.Index(objectBytes, moduleText[:256])
108*8fb009dcSAndroid Build Coastguard Worker	if offset < 0 {
109*8fb009dcSAndroid Build Coastguard Worker		return errors.New("did not find module prefix in object file")
110*8fb009dcSAndroid Build Coastguard Worker	}
111*8fb009dcSAndroid Build Coastguard Worker
112*8fb009dcSAndroid Build Coastguard Worker	if bytes.Index(objectBytes[offset+1:], moduleText[:256]) >= 0 {
113*8fb009dcSAndroid Build Coastguard Worker		return errors.New("found two occurrences of prefix in object file")
114*8fb009dcSAndroid Build Coastguard Worker	}
115*8fb009dcSAndroid Build Coastguard Worker
116*8fb009dcSAndroid Build Coastguard Worker	// Corrupt the module in the ELF.
117*8fb009dcSAndroid Build Coastguard Worker	objectBytes[offset] ^= 1
118*8fb009dcSAndroid Build Coastguard Worker
119*8fb009dcSAndroid Build Coastguard Worker	// Calculate the before and after hash of the module.
120*8fb009dcSAndroid Build Coastguard Worker	var zeroKey [64]byte
121*8fb009dcSAndroid Build Coastguard Worker	mac := hmac.New(sha512.New, zeroKey[:])
122*8fb009dcSAndroid Build Coastguard Worker	mac.Write(moduleText)
123*8fb009dcSAndroid Build Coastguard Worker	hashWas := mac.Sum(nil)
124*8fb009dcSAndroid Build Coastguard Worker
125*8fb009dcSAndroid Build Coastguard Worker	moduleText[0] ^= 1
126*8fb009dcSAndroid Build Coastguard Worker	mac.Reset()
127*8fb009dcSAndroid Build Coastguard Worker	mac.Write(moduleText)
128*8fb009dcSAndroid Build Coastguard Worker	newHash := mac.Sum(nil)
129*8fb009dcSAndroid Build Coastguard Worker
130*8fb009dcSAndroid Build Coastguard Worker	fmt.Printf("Found start of module at offset 0x%x (VMA 0x%x):\n", start-textSection.Addr, start)
131*8fb009dcSAndroid Build Coastguard Worker	fmt.Println(hex.Dump(moduleText[:128]))
132*8fb009dcSAndroid Build Coastguard Worker	fmt.Printf("\nHash of module was:          %x\n", hashWas)
133*8fb009dcSAndroid Build Coastguard Worker	fmt.Printf("Hash of corrupted module is: %x\n", newHash)
134*8fb009dcSAndroid Build Coastguard Worker
135*8fb009dcSAndroid Build Coastguard Worker	return os.WriteFile(outPath, objectBytes, 0755)
136*8fb009dcSAndroid Build Coastguard Worker}
137*8fb009dcSAndroid Build Coastguard Worker
138*8fb009dcSAndroid Build Coastguard Workerfunc main() {
139*8fb009dcSAndroid Build Coastguard Worker	if len(os.Args) != 3 {
140*8fb009dcSAndroid Build Coastguard Worker		usage()
141*8fb009dcSAndroid Build Coastguard Worker		os.Exit(1)
142*8fb009dcSAndroid Build Coastguard Worker	}
143*8fb009dcSAndroid Build Coastguard Worker
144*8fb009dcSAndroid Build Coastguard Worker	if err := do(os.Args[2], os.Args[1]); err != nil {
145*8fb009dcSAndroid Build Coastguard Worker		fmt.Fprintf(os.Stderr, "%s\n", err)
146*8fb009dcSAndroid Build Coastguard Worker		os.Exit(1)
147*8fb009dcSAndroid Build Coastguard Worker	}
148*8fb009dcSAndroid Build Coastguard Worker}
149*8fb009dcSAndroid Build Coastguard Worker
150*8fb009dcSAndroid Build Coastguard Workerfunc usage() {
151*8fb009dcSAndroid Build Coastguard Worker	fmt.Fprintf(os.Stderr, "Usage: %s <input binary> <output path>\n", os.Args[0])
152*8fb009dcSAndroid Build Coastguard Worker}
153