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