You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ut...@apache.org on 2019/10/21 17:51:39 UTC

[mynewt-artifact] branch master updated: Add support for protected TLVs

This is an automated email from the ASF dual-hosted git repository.

utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-artifact.git


The following commit(s) were added to refs/heads/master by this push:
     new 8fa4247  Add support for protected TLVs
8fa4247 is described below

commit 8fa4247999900fdd35a1bb60e8105711af884ffd
Author: Fabio Utzig <ut...@apache.org>
AuthorDate: Tue Oct 15 10:57:11 2019 -0300

    Add support for protected TLVs
    
    Protected TLVs is a new feature supported by MCUBoot beginning with
    version 1.4.0. This allows the hash+signature to also include a few TLVs
    that should be protected from modification by users. For more details:
    
    https://github.com/JuulLabs-OSS/mcuboot/blob/master/docs/design.md#protected-tlvs
---
 image/create.go | 81 +++++++++++++++++++++++++++++++++++---------------
 image/image.go  | 91 +++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 124 insertions(+), 48 deletions(-)

diff --git a/image/create.go b/image/create.go
index 8783b70..c51cfe6 100644
--- a/image/create.go
+++ b/image/create.go
@@ -337,7 +337,7 @@ func GenerateImage(opts ImageCreateOpts) (Image, error) {
 }
 
 func calcHash(initialHash []byte, hdr ImageHdr, pad []byte,
-	plainBody []byte) ([]byte, error) {
+	plainBody []byte, protTlvs []ImageTlv) ([]byte, error) {
 
 	hash := sha256.New()
 
@@ -371,22 +371,53 @@ func calcHash(initialHash []byte, hdr ImageHdr, pad []byte,
 		return nil, err
 	}
 
+	if len(protTlvs) > 0 {
+		trailer := ImageTrailer{
+			Magic:     IMAGE_PROT_TRAILER_MAGIC,
+			TlvTotLen: hdr.ProtSz,
+		}
+		if err := add(trailer); err != nil {
+			return nil, err
+		}
+
+		for _, tlv := range protTlvs {
+			if err := add(tlv.Header); err != nil {
+				return nil, err
+			}
+			if err := add(tlv.Data); err != nil {
+				return nil, err
+			}
+		}
+	}
+
 	return hash.Sum(nil), nil
 }
 
+func calcProtSize(protTlvs []ImageTlv) uint16 {
+	var size = uint16(0)
+	for _, tlv := range protTlvs {
+		size += IMAGE_TLV_SIZE
+		size += tlv.Header.Len
+	}
+	if size > 0 {
+		size += IMAGE_TRAILER_SIZE
+	}
+	return size
+}
+
 func (ic *ImageCreator) Create() (Image, error) {
 	img := Image{}
 
 	// First the header
 	img.Header = ImageHdr{
-		Magic: IMAGE_MAGIC,
-		Pad1:  0,
-		HdrSz: IMAGE_HEADER_SIZE,
-		Pad2:  0,
-		ImgSz: uint32(len(ic.Body)),
-		Flags: 0,
-		Vers:  ic.Version,
-		Pad3:  0,
+		Magic:  IMAGE_MAGIC,
+		Pad1:   0,
+		HdrSz:  IMAGE_HEADER_SIZE,
+		ProtSz: 0,
+		ImgSz:  uint32(len(ic.Body)),
+		Flags:  0,
+		Vers:   ic.Version,
+		Pad3:   0,
 	}
 
 	if !ic.Bootable {
@@ -411,6 +442,22 @@ func (ic *ImageCreator) Create() (Image, error) {
 		img.Pad = make([]byte, extra)
 	}
 
+	if ic.HWKeyIndex >= 0 {
+		tlv, err := GenerateHWKeyIndexTLV(uint32(ic.HWKeyIndex))
+		if err != nil {
+			return img, err
+		}
+		img.ProtTlvs = append(img.ProtTlvs, tlv)
+
+		tlv, err = GenerateNonceTLV(ic.Nonce)
+		if err != nil {
+			return img, err
+		}
+		img.ProtTlvs = append(img.ProtTlvs, tlv)
+	}
+
+	img.Header.ProtSz = calcProtSize(img.ProtTlvs)
+
 	payload := &ic.Body
 
 	// Followed by data.
@@ -429,7 +476,7 @@ func (ic *ImageCreator) Create() (Image, error) {
 		img.Body = append(img.Body, ic.Body...)
 	}
 
-	hashBytes, err := calcHash(ic.InitialHash, img.Header, img.Pad, *payload)
+	hashBytes, err := calcHash(ic.InitialHash, img.Header, img.Pad, *payload, img.ProtTlvs)
 	if err != nil {
 		return img, err
 	}
@@ -451,19 +498,7 @@ func (ic *ImageCreator) Create() (Image, error) {
 	}
 	img.Tlvs = append(img.Tlvs, tlvs...)
 
-	if ic.HWKeyIndex > 0 {
-		tlv, err := GenerateHWKeyIndexTLV(uint32(ic.HWKeyIndex))
-		if err != nil {
-			return img, err
-		}
-		img.Tlvs = append(img.Tlvs, tlv)
-
-		tlv, err = GenerateNonceTLV(ic.Nonce)
-		if err != nil {
-			return img, err
-		}
-		img.Tlvs = append(img.Tlvs, tlv)
-	} else if ic.CipherSecret != nil {
+	if ic.HWKeyIndex < 0 && ic.CipherSecret != nil {
 		tlv, err := GenerateEncTlv(ic.CipherSecret)
 		if err != nil {
 			return img, err
diff --git a/image/image.go b/image/image.go
index 6387393..9cba94a 100644
--- a/image/image.go
+++ b/image/image.go
@@ -31,8 +31,9 @@ import (
 )
 
 const (
-	IMAGE_MAGIC         = 0x96f3b83d /* Image header magic */
-	IMAGE_TRAILER_MAGIC = 0x6907     /* Image tlv info magic */
+	IMAGE_MAGIC              = 0x96f3b83d /* Image header magic */
+	IMAGE_TRAILER_MAGIC      = 0x6907     /* TLV info magic */
+	IMAGE_PROT_TRAILER_MAGIC = 0x6908     /* Protected TLV info magic */
 )
 
 const (
@@ -89,14 +90,14 @@ type ImageVersion struct {
 }
 
 type ImageHdr struct {
-	Magic uint32
-	Pad1  uint32
-	HdrSz uint16
-	Pad2  uint16
-	ImgSz uint32
-	Flags uint32
-	Vers  ImageVersion
-	Pad3  uint32
+	Magic  uint32
+	Pad1   uint32
+	HdrSz  uint16
+	ProtSz uint16
+	ImgSz  uint32
+	Flags  uint32
+	Vers   ImageVersion
+	Pad3   uint32
 }
 
 type ImageTlvHdr struct {
@@ -116,18 +117,21 @@ type ImageTrailer struct {
 }
 
 type Image struct {
-	Header ImageHdr
-	Pad    []byte
-	Body   []byte
-	Tlvs   []ImageTlv
+	Header   ImageHdr
+	Pad      []byte
+	Body     []byte
+	ProtTlvs []ImageTlv
+	Tlvs     []ImageTlv
 }
 
 type ImageOffsets struct {
-	Header    int
-	Body      int
-	Trailer   int
-	Tlvs      []int
-	TotalSize int
+	Header      int
+	Body        int
+	ProtTrailer int
+	Trailer     int
+	ProtTlvs    []int
+	Tlvs        []int
+	TotalSize   int
 }
 
 func ImageTlvTypeIsValid(tlvType uint8) bool {
@@ -190,10 +194,15 @@ func (tlv *ImageTlv) Write(w io.Writer) (int, error) {
 // Clone performs a deep copy of an image.
 func (img *Image) Clone() Image {
 	dup := Image{
-		Header: img.Header,
-		Pad:    append([]byte(nil), img.Pad...),
-		Body:   append([]byte(nil), img.Body...),
-		Tlvs:   make([]ImageTlv, len(img.Tlvs)),
+		Header:   img.Header,
+		Pad:      append([]byte(nil), img.Pad...),
+		Body:     append([]byte(nil), img.Body...),
+		ProtTlvs: make([]ImageTlv, len(img.ProtTlvs)),
+		Tlvs:     make([]ImageTlv, len(img.Tlvs)),
+	}
+
+	for i, tlv := range img.ProtTlvs {
+		dup.ProtTlvs[i] = tlv.Clone()
 	}
 
 	for i, tlv := range img.Tlvs {
@@ -291,7 +300,20 @@ func (i *Image) RemoveTlvsWithType(tlvType uint8) []ImageTlv {
 	})
 }
 
-// ImageTrailer constructs an image trailer corresponding to the given image.
+// ProtTrailer constructs a protected ImageTrailer corresponding to the given image.
+func (img *Image) ProtTrailer() ImageTrailer {
+	trailer := ImageTrailer{
+		Magic:     IMAGE_PROT_TRAILER_MAGIC,
+		TlvTotLen: IMAGE_TRAILER_SIZE,
+	}
+	for _, tlv := range img.ProtTlvs {
+		trailer.TlvTotLen += IMAGE_TLV_SIZE + tlv.Header.Len
+	}
+
+	return trailer
+}
+
+// Trailer constructs an ImageTrailer corresponding to the given image.
 func (img *Image) Trailer() ImageTrailer {
 	trailer := ImageTrailer{
 		Magic:     IMAGE_TRAILER_MAGIC,
@@ -321,7 +343,7 @@ func (i *Image) Hash() ([]byte, error) {
 
 // CalcHash calculates a SHA256 of the given image.
 func (i *Image) CalcHash() ([]byte, error) {
-	return calcHash(nil, i.Header, i.Pad, i.Body)
+	return calcHash(nil, i.Header, i.Pad, i.Body, i.ProtTlvs)
 }
 
 // WritePlusOffsets writes a binary image to the given writer.  It returns
@@ -351,6 +373,25 @@ func (i *Image) WritePlusOffsets(w io.Writer) (ImageOffsets, error) {
 	}
 	offset += size
 
+	if i.Header.ProtSz > 0 {
+		protTrailer := i.ProtTrailer()
+		offs.ProtTrailer = offset
+		err = binary.Write(w, binary.LittleEndian, &protTrailer)
+		if err != nil {
+			return offs, errors.Wrapf(err, "failed to write image trailer")
+		}
+		offset += IMAGE_TRAILER_SIZE
+
+		for _, tlv := range i.ProtTlvs {
+			offs.ProtTlvs = append(offs.ProtTlvs, offset)
+			size, err := tlv.Write(w)
+			if err != nil {
+				return offs, errors.Wrapf(err, "failed to write image TLV")
+			}
+			offset += size
+		}
+	}
+
 	trailer := i.Trailer()
 	offs.Trailer = offset
 	err = binary.Write(w, binary.LittleEndian, &trailer)