Skip to content

Commit

Permalink
automatically sign firmware on upload if not already signed
Browse files Browse the repository at this point in the history
  • Loading branch information
solipsis committed Mar 19, 2018
1 parent 6b89eab commit 1d909a4
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions pkg/keepkey/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"io"
"io/ioutil"
"math/big"
"os"
"strconv"
"strings"
"unicode/utf8"
Expand Down Expand Up @@ -511,6 +512,11 @@ func (kk *Keepkey) DecryptKeyValue(path []uint32, key string, val []byte) ([]byt
// to the device. It returns the number of bytes written and an error
func (kk *Keepkey) UploadFirmware(path string) (int, error) {

// Sign the firmware if it is not already signed
if err := signFirmware(path); err != nil {
return 0, err
}

// load firmware and compute the hash
data, err := ioutil.ReadFile(path)
if err != nil {
Expand Down Expand Up @@ -539,6 +545,62 @@ func (kk *Keepkey) UploadFirmware(path string) (int, error) {
return len(data), nil
}

// adds signature header to unsigned firmware. This signing process is unofficial and the device
// will warn that the firmware is not officially signed. For development purposes
// TODO: this method is probably unsafe concurrently
func signFirmware(path string) error {

var (
file *os.File
stat os.FileInfo
unsigned []byte
err error
)

// Read in the unsigned binary and get file metadata
if file, err = os.Open(path); err != nil {
return err
}
defer file.Close()
if unsigned, err = ioutil.ReadAll(file); err != nil {
return err
}
if stat, err = file.Stat(); err != nil {
return err
}

// Don't add signature again if it is already signed
if len(unsigned) > 4 && string(unsigned[0:4]) == "KPKY" {
return nil
}

buf := bytes.Buffer{}
buf.Write([]byte("KPKY")) // magic header

sizeBuf := make([]byte, 4)
binary.LittleEndian.PutUint32(sizeBuf, uint32(stat.Size()))
buf.Write(sizeBuf) // file size in little endian
buf.Write([]byte{0x01, 0x02, 0x03}) // signature indexes
buf.Write([]byte{0x01}) // flags

var reserved [52]byte
buf.Write(reserved[:]) // 52 reserved bytes

// insert 3 bogus signatures
for i := 0; i < 3; i++ {
sig := make([]byte, 64)
sig[0] = byte(10 + i)
buf.Write(sig)
}

// append binary
buf.Write(unsigned)

// Write out new signed binary
file.Close()
return ioutil.WriteFile(path, buf.Bytes(), 0644)
}

// WriteFlash writes the given block of data to the given address
// data should be at most 1024 bytes at a time
func (kk *Keepkey) FlashWrite(address uint32, data []byte) ([]byte, error) {
Expand Down

0 comments on commit 1d909a4

Please sign in to comment.