Merge pull request #24 from ccollins476ad/image-bin

image: Function to convert image to a byte slice
diff --git a/image/README.md b/image/README.md
new file mode 100644
index 0000000..b839e05
--- /dev/null
+++ b/image/README.md
@@ -0,0 +1,168 @@
+# Mynewt Images
+
+## Anatomy
+
+```
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                            Header                             |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ~                      Padding (optional)                       ~
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ~                                                               ~
+    ~                                                               ~
+    ~                             Body                              ~
+    ~                                                               ~
+    ~                                                               ~
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                 Protected Trailer (optional)                  |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ~                                                               ~
+    ~                   Protected TLVs (optional)                   ~
+    ~                                                               ~
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                            Trailer                            |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ~                                                               ~
+    ~                             TLVs                              ~
+    ~                                                               ~
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+```
+
+All fields are in host-byte order (typically little endian).
+
+### Header
+
+```
+     0                   1                   2                   3
+     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                      Magic (0x96f3b83d)                       |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                     Reserved1 (0x00000000)                    |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |          Header size          |        Protected size         |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                           Body size                           |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                             Flags                             |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    | Major version | Minor version |           Revision            |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                         Build number                          |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                     Reserved2 (0x00000000)                    |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+```
+
+| Field | Description | Notes |
+| ----- | ----------- | ----- |
+| Magic | Identifies the start of an image | |
+| Header size | 32 + the amount of padding that follows the header | |
+| Protected size | Size, in bytes, of the protected trailer PLUS the protected TLVs | 0 if no protected TLVs |
+| Body size | Size, in bytes, of the image body | |
+| Flags | One bit per flag | See below |
+| Major version | The first element of the version number | major.minor.revision.build |
+| Minor version | The second element of the version number | major.minor.revision.build |
+| Revision      | The third element of the version number | major.minor.revision.build |
+| Build number  | The fourth element of the version number | No meaning in semver |
+
+### Body
+
+The executable itself.  In encrypted images, this is the encrypted portion.
+
+### Protected trailer
+
+Describes the set of protected TLVs that follow.  This trailer is NOT present if there are no protected TLVs.
+
+```
+     0                   1                   2                   3
+     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |        Magic (0x6908)         |        Protected size         |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+```
+
+| Field | Description | Notes |
+| ----- | ----------- | ----- |
+| Magic | Identifies the start of the protected trailer | |
+| Protected size | Size, in bytes, of the protected trailer PLUS the protected TLVs | Identical to "Protected size" in image header |
+
+### Protected TLVs
+
+A sequence of TLV structures (see "TLVs" section for specifics).  The structure of these TLVs is identical to the non-protected TLVs.  The difference is that these TLVs are included as input to the image hash.
+
+### Trailer
+
+Describes the set of TLVs that follow.  This trailer is always present.
+
+```
+     0                   1                   2                   3
+     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |        Magic (0x6907)         |             Size              |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+```
+
+| Field | Description | Notes |
+| ----- | ----------- | ----- |
+| Magic | Identifies the start of the trailer | |
+| Size | Size, in bytes, of the trailer PLUS the TLVs | |
+
+### TLVs
+
+The TLVs (type-length-value) are a sequence of variable length structures containing image metadata.
+
+```
+     0                   1                   2                   3
+     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |     Type      | Reserved (00) |            Length             |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ~                                                               ~
+    ~                             Body                              ~
+    ~                                                               ~
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+```
+
+
+| Field | Description | Notes |
+| ----- | ----------- | ----- |
+| Type | Identifies the type of data in the TLV body | |
+| Length | The length, in bytes, of the TLV body | |
+| Body | Varies by type | |
+
+## Header flags
+
+Each header flag is represented by a single bit.  As with the other numeric fields, the flags field is in host byte order. 
+
+| Value | Description | Notes |
+| ----- | ----------- | ----- |
+| 0x00000004 | Encrypted by key in TLV | Implies the presence of an "enc" TLV |
+| 0x00000010 | Non-bootable | Second half of a split image |
+
+## TLV types
+
+| Value | Description | Notes |
+| ----- | ----------- | ----- |
+| 0x01  | Key hash | SHA256 of image verification key |
+| 0x10  | SHA256 | SHA256 of parts of the image (see below) |
+| 0x20  | Signature: RSA2048 | |
+| 0x21  | Signature: ECDSA224 | |
+| 0x22  | Signature: ECDSA256 | |
+| 0x23  | Signature: RSA3072 | |
+| 0x24  | Signature: ED25519 | |
+| 0x30  | Key-encrypting key: RSA | |
+| 0x31  | Key-encrypting key: KEK | |
+| 0x32  | Key-encrypting key: EC256 | |
+| 0x50  | Encryption nonce | |
+| 0x60  | Secret index | Indicates hardware-specific location of encryption key |
+
+### SHA256
+
+The sha256 is calculated using the following inputs:
+
+* Header
+* Post-header padding
+* Unencrypted image body
+* Protected trailer (if present)
+* Protected TLVs (if present)
diff --git a/image/create.go b/image/create.go
index 225a386..0217f2c 100644
--- a/image/create.go
+++ b/image/create.go
@@ -41,6 +41,7 @@
 	Body         []byte
 	Version      ImageVersion
 	SigKeys      []sec.PrivSignKey
+	Sections     []Section
 	HWKeyIndex   int
 	Nonce        []byte
 	PlainSecret  []byte
@@ -48,6 +49,7 @@
 	HeaderSize   int
 	InitialHash  []byte
 	Bootable     bool
+	UseLegacyTLV bool
 }
 
 type ImageCreateOpts struct {
@@ -56,9 +58,11 @@
 	SrcEncKeyIndex    int
 	Version           ImageVersion
 	SigKeys           []sec.PrivSignKey
+	Sections          []Section
 	LoaderHash        []byte
 	HdrPad            int
 	ImagePad          int
+	UseLegacyTLV      bool
 }
 
 type ECDSASig struct {
@@ -100,12 +104,21 @@
 	}
 }
 
-func GenerateHWKeyIndexTLV(secretIndex uint32) (ImageTlv, error) {
+// GenerateHWKeyIndexTLV creates a hardware key index TLV.
+func GenerateHWKeyIndexTLV(secretIndex uint32, useLegacyTLV bool) (ImageTlv, error) {
+	var tlvType uint8
 	id := make([]byte, 4)
 	binary.LittleEndian.PutUint32(id, secretIndex)
+
+	if useLegacyTLV {
+		tlvType = IMAGE_TLV_SECRET_ID_LEGACY
+	} else {
+		tlvType = IMAGE_TLV_SECRET_ID
+	}
+
 	return ImageTlv{
 		Header: ImageTlvHdr{
-			Type: IMAGE_TLV_SECRET_ID,
+			Type: tlvType,
 			Pad:  0,
 			Len:  uint16(len(id)),
 		},
@@ -113,10 +126,19 @@
 	}, nil
 }
 
-func GenerateNonceTLV(nonce []byte) (ImageTlv, error) {
+// GenerateNonceTLV creates a nonce TLV given a nonce.
+func GenerateNonceTLV(nonce []byte, useLegacyTLV bool) (ImageTlv, error) {
+	var tlvType uint8
+
+	if useLegacyTLV {
+		tlvType = IMAGE_TLV_AES_NONCE_LEGACY
+	} else {
+		tlvType = IMAGE_TLV_AES_NONCE
+	}
+
 	return ImageTlv{
 		Header: ImageTlvHdr{
-			Type: IMAGE_TLV_AES_NONCE,
+			Type: tlvType,
 			Pad:  0,
 			Len:  uint16(len(nonce)),
 		},
@@ -124,6 +146,7 @@
 	}, nil
 }
 
+// GenerateEncTlv creates an encryption-secret TLV given a secret.
 func GenerateEncTlv(cipherSecret []byte) (ImageTlv, error) {
 	var encType uint8
 
@@ -147,6 +170,25 @@
 	}, nil
 }
 
+// GenerateEncTlv creates an encryption-secret TLV given a secret.
+func GenerateSectionTlv(section Section) (ImageTlv, error) {
+	data := make([]byte, 8+len(section.Name))
+
+	binary.LittleEndian.PutUint32(data[0:], uint32(section.Offset))
+	binary.LittleEndian.PutUint32(data[4:], uint32(section.Size))
+	copy(data[8:], section.Name)
+
+	return ImageTlv{
+		Header: ImageTlvHdr{
+			Type: IMAGE_TLV_SECTION,
+			Pad:  0,
+			Len:  uint16(len(data)),
+		},
+		Data: data,
+	}, nil
+}
+
+// GenerateSig signs an image using an rsa key.
 func GenerateSigRsa(key sec.PrivSignKey, hash []byte) ([]byte, error) {
 	opts := rsa.PSSOptions{
 		SaltLength: rsa.PSSSaltLengthEqualsHash,
@@ -160,6 +202,7 @@
 	return signature, nil
 }
 
+// GenerateSig signs an image using an ec key.
 func GenerateSigEc(key sec.PrivSignKey, hash []byte) ([]byte, error) {
 	r, s, err := ecdsa.Sign(rand.Reader, key.Ec, hash)
 	if err != nil {
@@ -187,6 +230,7 @@
 	return signature, nil
 }
 
+// GenerateSig signs an image using an ed25519 key.
 func GenerateSigEd25519(key sec.PrivSignKey, hash []byte) ([]byte, error) {
 	sig := ed25519.Sign(*key.Ed25519, hash)
 
@@ -199,6 +243,7 @@
 	return sig, nil
 }
 
+// GenerateSig signs an image.
 func GenerateSig(key sec.PrivSignKey, hash []byte) (sec.Sig, error) {
 	pub := key.PubKey()
 	typ, err := pub.SigType()
@@ -238,6 +283,8 @@
 	}, nil
 }
 
+// BuildKeyHash produces a key-hash TLV given a public verification key.  Users
+// do not normally need to call this.  Call BuildSigTlvs instead.
 func BuildKeyHashTlv(keyBytes []byte) ImageTlv {
 	data := sec.RawKeyHash(keyBytes)
 	return ImageTlv{
@@ -250,6 +297,8 @@
 	}
 }
 
+// BuildSigTlvs signs an image and creates a pair of TLVs representing the
+// signature.
 func BuildSigTlvs(keys []sec.PrivSignKey, hash []byte) ([]ImageTlv, error) {
 	var tlvs []ImageTlv
 
@@ -282,6 +331,7 @@
 	return tlvs, nil
 }
 
+// GeneratePlainSecret randomly generates a 16-byte image-encrypting secret.
 func GeneratePlainSecret() ([]byte, error) {
 	plainSecret := make([]byte, 16)
 	if _, err := rand.Read(plainSecret); err != nil {
@@ -291,6 +341,7 @@
 	return plainSecret, nil
 }
 
+// GenerateImage produces an Image object from a set of image creation options.
 func GenerateImage(opts ImageCreateOpts) (Image, error) {
 	ic := NewImageCreator()
 
@@ -303,6 +354,8 @@
 	ic.Version = opts.Version
 	ic.SigKeys = opts.SigKeys
 	ic.HWKeyIndex = opts.SrcEncKeyIndex
+	ic.Sections = opts.Sections
+	ic.UseLegacyTLV = opts.UseLegacyTLV
 
 	if opts.LoaderHash != nil {
 		ic.InitialHash = opts.LoaderHash
@@ -365,6 +418,7 @@
 	return ri, nil
 }
 
+// calcHash calculates the sha256 for an image with the given components.
 func calcHash(initialHash []byte, hdr ImageHdr, pad []byte,
 	plainBody []byte, protTlvs []ImageTlv) ([]byte, error) {
 
@@ -422,6 +476,7 @@
 	return hash.Sum(nil), nil
 }
 
+// calcProtSize calculates the size, in bytes, of a set of protected TLVs.
 func calcProtSize(protTlvs []ImageTlv) uint16 {
 	var size = uint16(0)
 	for _, tlv := range protTlvs {
@@ -434,6 +489,7 @@
 	return size
 }
 
+// Create produces an Image object.
 func (ic *ImageCreator) Create() (Image, error) {
 	img := Image{}
 
@@ -472,13 +528,22 @@
 	}
 
 	if ic.HWKeyIndex >= 0 {
-		tlv, err := GenerateHWKeyIndexTLV(uint32(ic.HWKeyIndex))
+		tlv, err := GenerateHWKeyIndexTLV(uint32(ic.HWKeyIndex),
+			ic.UseLegacyTLV)
 		if err != nil {
 			return img, err
 		}
 		img.ProtTlvs = append(img.ProtTlvs, tlv)
 
-		tlv, err = GenerateNonceTLV(ic.Nonce)
+		tlv, err = GenerateNonceTLV(ic.Nonce, ic.UseLegacyTLV)
+		if err != nil {
+			return img, err
+		}
+		img.ProtTlvs = append(img.ProtTlvs, tlv)
+	}
+
+	for s := range ic.Sections {
+		tlv, err := GenerateSectionTlv(ic.Sections[s])
 		if err != nil {
 			return img, err
 		}
@@ -488,19 +553,28 @@
 	img.Header.ProtSz = calcProtSize(img.ProtTlvs)
 
 	// Followed by data.
+	var hashBytes []byte
+	var err error
 	if ic.PlainSecret != nil {
+		// For encrypted images, must calculate the hash with the plain
+		// body and encrypt the payload afterwards
+		img.Body = append(img.Body, ic.Body...)
+		hashBytes, err = img.CalcHash(ic.InitialHash)
+		if err != nil {
+			return img, err
+		}
 		encBody, err := sec.EncryptAES(ic.Body, ic.PlainSecret, ic.Nonce)
 		if err != nil {
 			return img, err
 		}
+		img.Body = nil
 		img.Body = append(img.Body, encBody...)
 	} else {
 		img.Body = append(img.Body, ic.Body...)
-	}
-
-	hashBytes, err := img.CalcHash(ic.InitialHash)
-	if err != nil {
-		return img, err
+		hashBytes, err = img.CalcHash(ic.InitialHash)
+		if err != nil {
+			return img, err
+		}
 	}
 
 	// Hash TLV.
diff --git a/image/image.go b/image/image.go
index 90191fc..d54eb82 100644
--- a/image/image.go
+++ b/image/image.go
@@ -57,33 +57,39 @@
  * Image trailer TLV types.
  */
 const (
-	IMAGE_TLV_KEYHASH   = 0x01
-	IMAGE_TLV_SHA256    = 0x10
-	IMAGE_TLV_RSA2048   = 0x20
-	IMAGE_TLV_ECDSA224  = 0x21
-	IMAGE_TLV_ECDSA256  = 0x22
-	IMAGE_TLV_RSA3072   = 0x23
-	IMAGE_TLV_ED25519   = 0x24
-	IMAGE_TLV_ENC_RSA   = 0x30
-	IMAGE_TLV_ENC_KEK   = 0x31
-	IMAGE_TLV_ENC_EC256 = 0x32
-	IMAGE_TLV_AES_NONCE = 0x50
-	IMAGE_TLV_SECRET_ID = 0x60
+	IMAGE_TLV_KEYHASH          = 0x01
+	IMAGE_TLV_SHA256           = 0x10
+	IMAGE_TLV_RSA2048          = 0x20
+	IMAGE_TLV_ECDSA224         = 0x21
+	IMAGE_TLV_ECDSA256         = 0x22
+	IMAGE_TLV_RSA3072          = 0x23
+	IMAGE_TLV_ED25519          = 0x24
+	IMAGE_TLV_ENC_RSA          = 0x30
+	IMAGE_TLV_ENC_KEK          = 0x31
+	IMAGE_TLV_ENC_EC256        = 0x32
+	IMAGE_TLV_AES_NONCE_LEGACY = 0x50
+	IMAGE_TLV_SECRET_ID_LEGACY = 0x60
+	IMAGE_TLV_AES_NONCE        = 0xa1
+	IMAGE_TLV_SECRET_ID        = 0xa2
+	IMAGE_TLV_SECTION          = 0xa3
 )
 
 var imageTlvTypeNameMap = map[uint8]string{
-	IMAGE_TLV_KEYHASH:   "KEYHASH",
-	IMAGE_TLV_SHA256:    "SHA256",
-	IMAGE_TLV_RSA2048:   "RSA2048",
-	IMAGE_TLV_ECDSA224:  "ECDSA224",
-	IMAGE_TLV_ECDSA256:  "ECDSA256",
-	IMAGE_TLV_RSA3072:   "RSA3072",
-	IMAGE_TLV_ED25519:   "ED25519",
-	IMAGE_TLV_ENC_RSA:   "ENC_RSA",
-	IMAGE_TLV_ENC_KEK:   "ENC_KEK",
-	IMAGE_TLV_ENC_EC256: "ENC_EC256",
-	IMAGE_TLV_AES_NONCE: "AES_NONCE",
-	IMAGE_TLV_SECRET_ID: "SEC_KEY_ID",
+	IMAGE_TLV_KEYHASH:          "KEYHASH",
+	IMAGE_TLV_SHA256:           "SHA256",
+	IMAGE_TLV_RSA2048:          "RSA2048",
+	IMAGE_TLV_ECDSA224:         "ECDSA224",
+	IMAGE_TLV_ECDSA256:         "ECDSA256",
+	IMAGE_TLV_RSA3072:          "RSA3072",
+	IMAGE_TLV_ED25519:          "ED25519",
+	IMAGE_TLV_ENC_RSA:          "ENC_RSA",
+	IMAGE_TLV_ENC_KEK:          "ENC_KEK",
+	IMAGE_TLV_ENC_EC256:        "ENC_EC256",
+	IMAGE_TLV_AES_NONCE:        "AES_NONCE",
+	IMAGE_TLV_SECRET_ID:        "SEC_KEY_ID",
+	IMAGE_TLV_AES_NONCE_LEGACY: "AES_NONCE",
+	IMAGE_TLV_SECRET_ID_LEGACY: "SEC_KEY_ID",
+	IMAGE_TLV_SECTION:          "SECTION",
 }
 
 var imageTlvTypeSigTypeMap = map[uint8]sec.SigType{
@@ -146,6 +152,12 @@
 	TotalSize   int
 }
 
+type Section struct {
+	Name   string
+	Size   int
+	Offset int
+}
+
 func ImageTlvTypeIsValid(tlvType uint8) bool {
 	_, ok := imageTlvTypeNameMap[tlvType]
 	return ok
@@ -740,9 +752,15 @@
 
 	tlvs := dup.FindProtTlvs(IMAGE_TLV_AES_NONCE)
 	if len(tlvs) != 1 {
-		return dup, errors.Errorf(
-			"failed to decrypt hw-encrypted image: "+
-				"wrong count of AES nonce TLVs; have=%d want=1", len(tlvs))
+		// try to find legacy TLV
+		tlvs := dup.FindProtTlvs(IMAGE_TLV_AES_NONCE_LEGACY)
+
+		if len(tlvs) != 1 {
+
+			return dup, errors.Errorf(
+				"failed to decrypt hw-encrypted image: "+
+					"wrong count of AES nonce TLVs; have=%d want=1", len(tlvs))
+		}
 	}
 	nonce := tlvs[0].Data
 
@@ -768,6 +786,8 @@
 
 	img.RemoveProtTlvsWithType(IMAGE_TLV_AES_NONCE)
 	img.RemoveProtTlvsWithType(IMAGE_TLV_SECRET_ID)
+	img.RemoveProtTlvsWithType(IMAGE_TLV_AES_NONCE_LEGACY)
+	img.RemoveProtTlvsWithType(IMAGE_TLV_SECRET_ID_LEGACY)
 
 	return img, nil
 }
diff --git a/image/map.go b/image/map.go
index 947cb88..7e95aa0 100644
--- a/image/map.go
+++ b/image/map.go
@@ -31,6 +31,7 @@
 		"_offset": offset,
 		"flags":   h.Flags,
 		"hdr_sz":  h.HdrSz,
+		"prot_sz": h.ProtSz,
 		"img_sz":  h.ImgSz,
 		"magic":   h.Magic,
 		"vers":    h.Vers.String(),
@@ -72,6 +73,12 @@
 	m := map[string]interface{}{}
 	m["header"] = img.Header.Map(offs.Header)
 	m["body"] = rawBodyMap(offs.Body)
+
+	if img.Header.ProtSz > 0 {
+		protTrailer := img.ProtTrailer()
+		m["prot_trailer"] = protTrailer.Map(offs.ProtTrailer)
+	}
+
 	trailer := img.Trailer()
 	m["trailer"] = trailer.Map(offs.Trailer)
 
diff --git a/sec/encrypt.go b/sec/encrypt.go
index 85d4571..97aaaec 100644
--- a/sec/encrypt.go
+++ b/sec/encrypt.go
@@ -31,9 +31,10 @@
 	"crypto/sha256"
 	"crypto/x509"
 	"encoding/base64"
-	"golang.org/x/crypto/hkdf"
 	"io"
 
+	"golang.org/x/crypto/hkdf"
+
 	keywrap "github.com/NickBall/go-aes-key-wrap"
 	"github.com/apache/mynewt-artifact/errors"
 )
@@ -251,17 +252,18 @@
 }
 
 func EncryptAES(plain []byte, secret []byte, nonce []byte) ([]byte, error) {
+	if len(nonce) > 16 {
+		return nil, errors.Errorf("AES nonce has invalid length: have=%d want<=16", len(nonce))
+	}
+
 	blk, err := aes.NewCipher(secret)
 	if err != nil {
 		return nil, errors.Errorf("Failed to create block cipher")
 	}
 
-	var iv []byte
-	if nonce == nil {
-		iv = make([]byte, 16)
-	} else {
-		zeros := make([]byte, 8)
-		iv = append(nonce, zeros...)
+	iv := nonce
+	for len(iv) < 16 {
+		iv = append(iv, 0)
 	}
 
 	stream := cipher.NewCTR(blk, iv)