You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/11/14 18:11:03 UTC

[GitHub] ccollins476ad closed pull request #238: Support arbitrary lists of signing keys

ccollins476ad closed pull request #238: Support arbitrary lists of signing keys
URL: https://github.com/apache/mynewt-newt/pull/238
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/newt/builder/build.go b/newt/builder/build.go
index ff6d5054..9db22135 100644
--- a/newt/builder/build.go
+++ b/newt/builder/build.go
@@ -285,7 +285,7 @@ func (b *Builder) newCompiler(bpkg *BuildPackage,
 			return nil, err
 		}
 
-		log.Warnf("Unsupported build profile for package, using default build profile " +
+		log.Warnf("Unsupported build profile for package, using default build profile "+
 			"(pkg=\"%s\" build_profile=\"%s\" OS=\"%s\")",
 			bpkg.rpkg.Lpkg.FullName(), buildProfile, runtime.GOOS)
 
@@ -794,7 +794,8 @@ func (b *Builder) buildRomElf(common *symbol.SymbolMap) error {
 }
 
 func (b *Builder) CreateImage(version string,
-	keystr string, keyId uint8, loaderImg *image.Image) (*image.Image, error) {
+	keystrs []string, keyId uint8,
+	loaderImg *image.Image) (*image.Image, error) {
 
 	img, err := image.NewImage(b.AppBinPath(), b.AppImgPath())
 	if err != nil {
@@ -806,16 +807,18 @@ func (b *Builder) CreateImage(version string,
 		return nil, err
 	}
 
-	if keystr != "" {
-		err = img.SetSigningKey(keystr, keyId)
-		if err != nil {
+	if len(keystrs) == 1 {
+		if err := img.SetKeyV1(keystrs[0], keyId); err != nil {
+			return nil, err
+		}
+	} else {
+		if err := img.SetKeys(keystrs); err != nil {
 			return nil, err
 		}
 	}
 
 	img.HeaderSize = uint(b.targetBuilder.target.HeaderSize)
-	err = img.Generate(loaderImg)
-	if err != nil {
+	if err := img.Generate(loaderImg); err != nil {
 		return nil, err
 	}
 
diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index 9ee7317d..f5fa8e64 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -867,7 +867,7 @@ func (t *TargetBuilder) verifyImgSizes(li *image.Image, ai *image.Image) error {
 
 // @return                      app-image, loader-image, error
 func (t *TargetBuilder) CreateImages(version string,
-	keystr string, keyId uint8) (*image.Image, *image.Image, error) {
+	keystrs []string, keyId uint8) (*image.Image, *image.Image, error) {
 
 	if err := t.Build(); err != nil {
 		return nil, nil, err
@@ -883,7 +883,7 @@ func (t *TargetBuilder) CreateImages(version string,
 	}
 
 	if t.LoaderBuilder != nil {
-		loaderImg, err = t.LoaderBuilder.CreateImage(version, keystr, keyId,
+		loaderImg, err = t.LoaderBuilder.CreateImage(version, keystrs, keyId,
 			nil)
 		if err != nil {
 			return nil, nil, err
@@ -900,7 +900,7 @@ func (t *TargetBuilder) CreateImages(version string,
 		}
 	}
 
-	appImg, err = t.AppBuilder.CreateImage(version, keystr, keyId, loaderImg)
+	appImg, err = t.AppBuilder.CreateImage(version, keystrs, keyId, loaderImg)
 	if err != nil {
 		return nil, nil, err
 	}
diff --git a/newt/cli/image_cmds.go b/newt/cli/image_cmds.go
index 3063d3e7..73459ed4 100644
--- a/newt/cli/image_cmds.go
+++ b/newt/cli/image_cmds.go
@@ -32,9 +32,28 @@ import (
 var useV1 bool
 var useV2 bool
 
+func parseKeyArgs(args []string) ([]string, uint8, error) {
+	if len(args) == 0 {
+		return nil, 0, nil
+	}
+
+	if len(args) == 1 {
+		return args, 0, nil
+	}
+
+	if image.UseV1 {
+		keyId64, err := strconv.ParseUint(args[1], 10, 8)
+		if err != nil {
+			return nil, 0, util.NewNewtError("Key ID must be between 0-255")
+		}
+		return args[:1], uint8(keyId64), nil
+	}
+
+	return args, 0, nil
+}
+
 func createImageRunCmd(cmd *cobra.Command, args []string) {
 	var keyId uint8
-	var keystr string
 
 	if len(args) < 2 {
 		NewtUsage(cmd, util.NewNewtError("Must specify target and version"))
@@ -59,26 +78,18 @@ func createImageRunCmd(cmd *cobra.Command, args []string) {
 
 	version := args[1]
 
-	if len(args) > 2 {
-		if len(args) > 3 {
-			keyId64, err := strconv.ParseUint(args[3], 10, 8)
-			if err != nil {
-				NewtUsage(cmd,
-					util.NewNewtError("Key ID must be between 0-255"))
-			}
-			keyId = uint8(keyId64)
-		}
-		keystr = args[2]
-	}
-
 	b, err := builder.NewTargetBuilder(t)
 	if err != nil {
 		NewtUsage(nil, err)
 	}
 
-	if _, _, err := b.CreateImages(version, keystr, keyId); err != nil {
+	keystrs, keyId, err := parseKeyArgs(args[2:])
+	if err != nil {
+		NewtUsage(cmd, err)
+	}
+
+	if _, _, err := b.CreateImages(version, keystrs, keyId); err != nil {
 		NewtUsage(nil, err)
-		return
 	}
 }
 
@@ -116,7 +127,7 @@ func resignImageRunCmd(cmd *cobra.Command, args []string) {
 			keyId = uint8(keyId64)
 		}
 		keystr = args[1]
-		err = img.SetSigningKey(keystr, keyId)
+		err = img.SetKeyV1(keystr, keyId)
 		if err != nil {
 			NewtUsage(nil, err)
 			return
@@ -151,10 +162,12 @@ func AddImageCommands(cmd *cobra.Command) {
 	createImageHelpEx := "  newt create-image my_target1 1.3.0\n"
 	createImageHelpEx += "  newt create-image my_target1 1.3.0.3\n"
 	createImageHelpEx += "  newt create-image my_target1 1.3.0.3 private.pem\n"
-	createImageHelpEx += "  newt create-image my_target1 1.3.0.3 private.pem 5\n"
+	createImageHelpEx +=
+		"  newt create-image -2 my_target1 1.3.0.3 private-1.pem private-2.pem\n"
 
 	createImageCmd := &cobra.Command{
-		Use:     "create-image <target-name> <version> [signing-key [key-id]]",
+		Use: "create-image <target-name> <version> [signing-key-1] " +
+			"[signing-key-2] [...]",
 		Short:   "Add image header to target binary",
 		Long:    createImageHelpText,
 		Example: createImageHelpEx,
diff --git a/newt/cli/run_cmds.go b/newt/cli/run_cmds.go
index 49a2e4d3..d3f3ed90 100644
--- a/newt/cli/run_cmds.go
+++ b/newt/cli/run_cmds.go
@@ -88,11 +88,20 @@ func runRunCmd(cmd *cobra.Command, args []string) {
 		}
 
 		if len(version) > 0 {
-			_, _, err = b.CreateImages(version, "", 0)
+			var keystrs []string
+			var keyId uint8
+
+			if len(args) > 2 {
+				keystrs, keyId, err = parseKeyArgs(args[2:])
+				if err != nil {
+					NewtUsage(cmd, err)
+				}
+			}
+
+			_, _, err = b.CreateImages(version, keystrs, keyId)
 			if err != nil {
 				NewtUsage(cmd, err)
 			}
-
 		}
 
 		if err := b.Load(extraJtagCmd); err != nil {
@@ -113,6 +122,8 @@ func AddRunCommands(cmd *cobra.Command) {
 		" - debug <target>\n\n" +
 		"Note if version number is omitted, create-image step is skipped\n"
 	runHelpEx := "  newt run <target-name> [<version>]\n"
+	runHelpEx +=
+		"  newt run -2 my_target1 1.3.0.3 private-1.pem private-2.pem\n"
 
 	runCmd := &cobra.Command{
 		Use:     "run",
diff --git a/newt/image/image.go b/newt/image/image.go
index bbc6b5a7..278804e0 100644
--- a/newt/image/image.go
+++ b/newt/image/image.go
@@ -67,13 +67,18 @@ type ImageVersion struct {
 	BuildNum uint32
 }
 
+type ImageKey struct {
+	// Only one of these members is non-nil.
+	Rsa *rsa.PrivateKey
+	Ec  *ecdsa.PrivateKey
+}
+
 type Image struct {
 	SourceBin  string
 	SourceImg  string
 	TargetImg  string
 	Version    ImageVersion
-	SigningRSA *rsa.PrivateKey
-	SigningEC  *ecdsa.PrivateKey
+	Keys       []ImageKey
 	KeyId      uint8
 	Hash       []byte
 	SrcSkip    uint // Number of bytes to skip from the source image.
@@ -327,8 +332,8 @@ func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
 		 */
 		privKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
 		if err != nil {
-			return nil, util.NewNewtError(fmt.Sprintf("Private key parsing "+
-				"failed: %s", err))
+			return nil, util.FmtNewtError(
+				"Private key parsing failed: %s", err)
 		}
 	}
 	if block != nil && block.Type == "EC PRIVATE KEY" {
@@ -337,8 +342,8 @@ func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
 		 */
 		privKey, err = x509.ParseECPrivateKey(block.Bytes)
 		if err != nil {
-			return nil, util.NewNewtError(fmt.Sprintf("Private key parsing "+
-				"failed: %s", err))
+			return nil, util.FmtNewtError(
+				"Private key parsing failed: %s", err)
 		}
 	}
 	if block != nil && block.Type == "PRIVATE KEY" {
@@ -347,8 +352,8 @@ func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
 		// the key itself.
 		privKey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
 		if err != nil {
-			return nil, util.NewNewtError(fmt.Sprintf("Private key parsing "+
-				"failed: %s", err))
+			return nil, util.FmtNewtError(
+				"Private key parsing failed: %s", err)
 		}
 	}
 	if block != nil && block.Type == "ENCRYPTED PRIVATE KEY" {
@@ -367,77 +372,115 @@ func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
 	return privKey, nil
 }
 
-func (image *Image) SetSigningKey(fileName string, keyId uint8) error {
-	keyBytes, err := ioutil.ReadFile(fileName)
+func readKey(filename string) (ImageKey, error) {
+	key := ImageKey{}
+
+	keyBytes, err := ioutil.ReadFile(filename)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Error reading key file: %s", err))
+		return key, util.FmtNewtError("Error reading key file: %s", err)
 	}
 
-	image.KeyId = keyId
 	privKey, err := ParsePrivateKey(keyBytes)
 	if err != nil {
-		return err
+		return key, err
 	}
 
 	switch priv := privKey.(type) {
 	case *rsa.PrivateKey:
-		image.SigningRSA = priv
+		key.Rsa = priv
 	case *ecdsa.PrivateKey:
-		image.SigningEC = priv
+		key.Ec = priv
 	default:
-		return util.NewNewtError("Unknown private key format")
+		return key, util.NewNewtError("Unknown private key format")
+	}
+
+	return key, nil
+}
+
+func (key *ImageKey) assertValid() {
+	if key.Rsa == nil && key.Ec == nil {
+		panic("invalid key; neither RSA nor ECC")
+	}
+
+	if key.Rsa != nil && key.Ec != nil {
+		panic("invalid key; neither RSA nor ECC")
+	}
+}
+
+func (image *Image) SetKeys(filenames []string) error {
+	for _, filename := range filenames {
+		key, err := readKey(filename)
+		if err != nil {
+			return err
+		}
+
+		image.Keys = append(image.Keys, key)
 	}
 
 	return nil
 }
 
-func (image *Image) sigHdrTypeV1() (uint32, error) {
-	if image.SigningRSA != nil {
+func (image *Image) SetKeyV1(filename string, keyId uint8) error {
+	key, err := readKey(filename)
+	if err != nil {
+		return err
+	}
+
+	image.KeyId = keyId
+	image.Keys = []ImageKey{key}
+
+	return nil
+}
+
+func (key *ImageKey) sigHdrTypeV1() (uint32, error) {
+	key.assertValid()
+
+	if key.Rsa != nil {
 		if UseRsaPss {
 			return IMAGEv1_F_PKCS1_PSS_RSA2048_SHA256, nil
 		} else {
 			return IMAGEv1_F_PKCS15_RSA2048_SHA256, nil
 		}
-	} else if image.SigningEC != nil {
-		switch image.SigningEC.Curve.Params().Name {
+	} else {
+		switch key.Ec.Curve.Params().Name {
 		case "P-224":
 			return IMAGEv1_F_ECDSA224_SHA256, nil
 		case "P-256":
 			return IMAGEv1_F_ECDSA256_SHA256, nil
 		default:
-			return 0, util.NewNewtError("Unsupported ECC curve")
+			return 0, util.FmtNewtError("Unsupported ECC curve")
 		}
-	} else {
-		return 0, nil
 	}
 }
 
-func (image *Image) sigKeyHash() ([]uint8, error) {
-	if image.SigningRSA != nil {
-		pubkey, _ := asn1.Marshal(image.SigningRSA.PublicKey)
+func (key *ImageKey) sigKeyHash() ([]uint8, error) {
+	key.assertValid()
+
+	if key.Rsa != nil {
+		pubkey, _ := asn1.Marshal(key.Rsa.PublicKey)
 		sum := sha256.Sum256(pubkey)
 		return sum[:4], nil
-	} else if image.SigningEC != nil {
-		switch image.SigningEC.Curve.Params().Name {
+	} else {
+		switch key.Ec.Curve.Params().Name {
 		case "P-224":
 			fallthrough
 		case "P-256":
-			pubkey, _ := x509.MarshalPKIXPublicKey(&image.SigningEC.PublicKey)
+			pubkey, _ := x509.MarshalPKIXPublicKey(&key.Ec.PublicKey)
 			sum := sha256.Sum256(pubkey)
 			return sum[:4], nil
 		default:
-			return []uint8{}, util.NewNewtError("Unsupported ECC curve")
+			return nil, util.NewNewtError("Unsupported ECC curve")
 		}
-	} else {
-		return []uint8{}, util.NewNewtError("No public key to hash")
 	}
 }
 
-func (image *Image) sigLen() uint16 {
-	if image.SigningRSA != nil {
+func (key *ImageKey) sigLen() uint16 {
+	key.assertValid()
+
+	if key.Rsa != nil {
 		return 256
-	} else if image.SigningEC != nil {
-		switch image.SigningEC.Curve.Params().Name {
+	} else {
+		switch key.Ec.Curve.Params().Name {
 		case "P-224":
 			return 68
 		case "P-256":
@@ -445,56 +488,52 @@ func (image *Image) sigLen() uint16 {
 		default:
 			return 0
 		}
-	} else {
-		return 0
 	}
 }
 
-func (image *Image) sigTlvTypeV1() uint8 {
-	if image.SigningRSA != nil {
-		return IMAGEv1_TLV_RSA2048
-	} else if image.SigningEC != nil {
-		switch image.SigningEC.Curve.Params().Name {
-		case "P-224":
-			return IMAGEv1_TLV_ECDSA224
-		case "P-256":
-			return IMAGEv1_TLV_ECDSA256
-		default:
-			return 0
-		}
-	} else {
-		return 0
-	}
-}
+func (key *ImageKey) sigTlvType() uint8 {
+	key.assertValid()
 
-func (image *Image) sigTlvType() uint8 {
-	if image.SigningRSA != nil {
-		return IMAGE_TLV_RSA2048
-	} else if image.SigningEC != nil {
-		switch image.SigningEC.Curve.Params().Name {
-		case "P-224":
-			return IMAGE_TLV_ECDSA224
-		case "P-256":
-			return IMAGE_TLV_ECDSA256
-		default:
-			return 0
+	if UseV1 {
+		if key.Rsa != nil {
+			return IMAGEv1_TLV_RSA2048
+		} else {
+			switch key.Ec.Curve.Params().Name {
+			case "P-224":
+				return IMAGEv1_TLV_ECDSA224
+			case "P-256":
+				return IMAGEv1_TLV_ECDSA256
+			default:
+				return 0
+			}
 		}
 	} else {
-		return 0
+		if key.Rsa != nil {
+			return IMAGE_TLV_RSA2048
+		} else {
+			switch key.Ec.Curve.Params().Name {
+			case "P-224":
+				return IMAGE_TLV_ECDSA224
+			case "P-256":
+				return IMAGE_TLV_ECDSA256
+			default:
+				return 0
+			}
+		}
 	}
 }
 
 func (image *Image) ReSign() error {
 	srcImg, err := os.Open(image.SourceImg)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't open image file %s: %s",
-			image.SourceImg, err.Error()))
+		return util.FmtNewtError("Can't open image file %s: %s",
+			image.SourceImg, err.Error())
 	}
 
 	srcInfo, err := srcImg.Stat()
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't stat image file %s: %s",
-			image.SourceImg, err.Error()))
+		return util.FmtNewtError("Can't stat image file %s: %s",
+			image.SourceImg, err.Error())
 	}
 
 	var hdr1 ImageHdrV1
@@ -508,15 +547,15 @@ func (image *Image) ReSign() error {
 		err = binary.Read(srcImg, binary.LittleEndian, &hdr2)
 	}
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failing to access image %s: %s",
-			image.SourceImg, err.Error()))
+		return util.FmtNewtError("Failing to access image %s: %s",
+			image.SourceImg, err.Error())
 	}
 	if hdr1.Magic == IMAGEv1_MAGIC {
 		if uint32(srcInfo.Size()) !=
 			uint32(hdr1.HdrSz)+hdr1.ImgSz+uint32(hdr1.TlvSz) {
 
-			return util.NewNewtError(fmt.Sprintf("File %s is not an image\n",
-				image.SourceImg))
+			return util.FmtNewtError("File %s is not an image\n",
+				image.SourceImg)
 		}
 		imgSz = hdr1.ImgSz
 		hdrSz = hdr1.HdrSz
@@ -527,8 +566,8 @@ func (image *Image) ReSign() error {
 			hdr1.Vers.BuildNum)
 	} else if hdr2.Magic == IMAGE_MAGIC {
 		if uint32(srcInfo.Size()) < uint32(hdr2.HdrSz)+hdr2.ImgSz {
-			return util.NewNewtError(fmt.Sprintf("File %s is not an image\n",
-				image.SourceImg))
+			return util.FmtNewtError("File %s is not an image\n",
+				image.SourceImg)
 		}
 		imgSz = hdr2.ImgSz
 		hdrSz = hdr2.HdrSz
@@ -538,15 +577,15 @@ func (image *Image) ReSign() error {
 			hdr2.Vers.Major, hdr2.Vers.Minor, hdr2.Vers.Rev,
 			hdr2.Vers.BuildNum)
 	} else {
-		return util.NewNewtError(fmt.Sprintf("File %s is not an image\n",
-			image.SourceImg))
+		return util.FmtNewtError("File %s is not an image\n",
+			image.SourceImg)
 	}
 	srcImg.Seek(int64(hdrSz), 0)
 
 	tmpBin, err := ioutil.TempFile("", "")
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Creating temp file failed: %s",
-			err.Error()))
+		return util.FmtNewtError("Creating temp file failed: %s",
+			err.Error())
 	}
 	tmpBinName := tmpBin.Name()
 	defer os.Remove(tmpBinName)
@@ -557,8 +596,8 @@ func (image *Image) ReSign() error {
 	srcImg.Close()
 	tmpBin.Close()
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Cannot copy to tmpfile %s: %s",
-			tmpBin.Name(), err.Error()))
+		return util.FmtNewtError("Cannot copy to tmpfile %s: %s",
+			tmpBin.Name(), err.Error())
 	}
 
 	image.SourceBin = tmpBinName
@@ -568,25 +607,170 @@ func (image *Image) ReSign() error {
 	return image.Generate(nil)
 }
 
+func generateSigRsa(key *rsa.PrivateKey, hash []byte) ([]byte, error) {
+	var signature []byte
+	var err error
+
+	if UseRsaPss || !UseV1 {
+		opts := rsa.PSSOptions{
+			SaltLength: rsa.PSSSaltLengthEqualsHash,
+		}
+		signature, err = rsa.SignPSS(
+			rand.Reader, key, crypto.SHA256, hash, &opts)
+	} else {
+		signature, err = rsa.SignPKCS1v15(
+			rand.Reader, key, crypto.SHA256, hash)
+	}
+	if err != nil {
+		return nil, util.FmtNewtError("Failed to compute signature: %s", err)
+	}
+
+	return signature, nil
+}
+
+func generateSigEc(key *ecdsa.PrivateKey, hash []byte) ([]byte, error) {
+	r, s, err := ecdsa.Sign(rand.Reader, key, hash)
+	if err != nil {
+		return nil, util.FmtNewtError("Failed to compute signature: %s", err)
+	}
+
+	ECDSA := ECDSASig{
+		R: r,
+		S: s,
+	}
+
+	signature, err := asn1.Marshal(ECDSA)
+	if err != nil {
+		return nil, util.FmtNewtError("Failed to construct signature: %s", err)
+	}
+
+	return signature, nil
+}
+
+func generateSigTlvRsa(key ImageKey, hash []byte) ([]byte, error) {
+	tlv := &ImageTrailerTlv{
+		Type: key.sigTlvType(),
+		Pad:  0,
+		Len:  256, /* 2048 bits */
+	}
+
+	sig, err := generateSigRsa(key.Rsa, hash)
+	if err != nil {
+		return nil, err
+	}
+
+	b := &bytes.Buffer{}
+
+	err = binary.Write(b, binary.LittleEndian, tlv)
+	if err != nil {
+		return nil, util.FmtNewtError(
+			"Failed to serialize image trailer: %s", err.Error())
+	}
+	_, err = b.Write(sig)
+	if err != nil {
+		return nil, util.FmtNewtError(
+			"Failed to append sig: %s", err.Error())
+	}
+
+	return b.Bytes(), nil
+}
+
+func generateSigTlvEc(key ImageKey, hash []byte) ([]byte, error) {
+	sig, err := generateSigEc(key.Ec, hash)
+	if err != nil {
+		return nil, err
+	}
+
+	sigLen := key.sigLen()
+	if len(sig) > int(sigLen) {
+		return nil, util.FmtNewtError("Something is really wrong\n")
+	}
+
+	tlv := &ImageTrailerTlv{
+		Type: key.sigTlvType(),
+		Pad:  0,
+		Len:  sigLen,
+	}
+
+	b := &bytes.Buffer{}
+
+	if err := binary.Write(b, binary.LittleEndian, tlv); err != nil {
+		return nil, util.FmtNewtError(
+			"Failed to serialize image trailer: %s", err.Error())
+	}
+
+	if _, err := b.Write(sig); err != nil {
+		return nil, util.FmtNewtError("Failed to append sig: %s", err.Error())
+	}
+
+	pad := make([]byte, int(sigLen)-len(sig))
+	if _, err := b.Write(pad); err != nil {
+		return nil, util.FmtNewtError(
+			"Failed to serialize image trailer: %s", err.Error())
+	}
+
+	return b.Bytes(), nil
+}
+
+func generateSigTlv(key ImageKey, hash []byte) ([]byte, error) {
+	key.assertValid()
+
+	if key.Rsa != nil {
+		return generateSigTlvRsa(key, hash)
+	} else {
+		return generateSigTlvEc(key, hash)
+	}
+}
+
+func generateKeyHashTlv(key ImageKey) ([]byte, error) {
+	key.assertValid()
+
+	keyHash, err := key.sigKeyHash()
+	if err != nil {
+		return nil, util.FmtNewtError(
+			"Failed to compute hash of the public key: %s", err.Error())
+	}
+
+	tlv := &ImageTrailerTlv{
+		Type: IMAGE_TLV_KEYHASH,
+		Pad:  0,
+		Len:  uint16(len(keyHash)),
+	}
+
+	b := &bytes.Buffer{}
+
+	if err := binary.Write(b, binary.LittleEndian, tlv); err != nil {
+		return nil, util.FmtNewtError(
+			"Failed to serial image trailer: %s", err.Error())
+	}
+
+	if _, err := b.Write(keyHash); err != nil {
+		return nil, util.FmtNewtError(
+			"Failed to append key hash: %s", err.Error())
+	}
+
+	return b.Bytes(), nil
+}
+
 func (image *Image) generateV1(loader *Image) error {
 	binFile, err := os.Open(image.SourceBin)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't open app binary: %s",
-			err.Error()))
+		return util.FmtNewtError("Can't open app binary: %s",
+			err.Error())
 	}
 	defer binFile.Close()
 
 	binInfo, err := binFile.Stat()
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't stat app binary %s: %s",
-			image.SourceBin, err.Error()))
+		return util.FmtNewtError("Can't stat app binary %s: %s",
+			image.SourceBin, err.Error())
 	}
 
 	imgFile, err := os.OpenFile(image.TargetImg,
 		os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't open target image %s: %s",
-			image.TargetImg, err.Error()))
+		return util.FmtNewtError("Can't open target image %s: %s",
+			image.TargetImg, err.Error())
 	}
 	defer imgFile.Close()
 
@@ -598,8 +782,7 @@ func (image *Image) generateV1(loader *Image) error {
 	if loader != nil {
 		err = binary.Write(hash, binary.LittleEndian, loader.Hash)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to seed hash: %s",
-				err.Error()))
+			return util.FmtNewtError("Failed to seed hash: %s", err.Error())
 		}
 	}
 
@@ -619,15 +802,13 @@ func (image *Image) generateV1(loader *Image) error {
 		Pad3:  0,
 	}
 
-	hdr.Flags, err = image.sigHdrTypeV1()
-	if err != nil {
-		return err
-	}
-	if hdr.Flags != 0 {
-		/*
-		 * Signature present
-		 */
-		hdr.TlvSz = 4 + image.sigLen()
+	if len(image.Keys) > 0 {
+		hdr.Flags, err = image.Keys[0].sigHdrTypeV1()
+		if err != nil {
+			return err
+		}
+
+		hdr.TlvSz = 4 + image.Keys[0].sigLen()
 		hdr.KeyId = image.KeyId
 	}
 
@@ -645,7 +826,8 @@ func (image *Image) generateV1(loader *Image) error {
 		 * the image when it is padded.
 		 */
 		if image.HeaderSize < IMAGE_HEADER_SIZE {
-			return util.NewNewtError(fmt.Sprintf("Image header must be at least %d bytes", IMAGE_HEADER_SIZE))
+			return util.FmtNewtError(
+				"Image header must be at least %d bytes", IMAGE_HEADER_SIZE)
 		}
 
 		hdr.HdrSz = uint16(image.HeaderSize)
@@ -653,13 +835,12 @@ func (image *Image) generateV1(loader *Image) error {
 
 	err = binary.Write(imgFile, binary.LittleEndian, hdr)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s",
-			err.Error()))
+		return util.FmtNewtError("Failed to serialize image hdr: %s",
+			err.Error())
 	}
 	err = binary.Write(hash, binary.LittleEndian, hdr)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s",
-			err.Error()))
+		return util.FmtNewtError("Failed to hash data: %s", err.Error())
 	}
 
 	if image.HeaderSize > IMAGE_HEADER_SIZE {
@@ -671,14 +852,13 @@ func (image *Image) generateV1(loader *Image) error {
 
 		_, err = imgFile.Write(buf)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to write padding: %s",
-				err.Error()))
+			return util.FmtNewtError(
+				"Failed to write padding: %s", err.Error())
 		}
 
 		_, err = hash.Write(buf)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to hash padding: %s",
-				err.Error()))
+			return util.FmtNewtError("Failed to hash padding: %s", err.Error())
 		}
 	}
 
@@ -689,8 +869,8 @@ func (image *Image) generateV1(loader *Image) error {
 		buf := make([]byte, image.SrcSkip)
 		_, err = binFile.Read(buf)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s",
-				image.SourceBin, err.Error()))
+			return util.FmtNewtError(
+				"Failed to read from %s: %s", image.SourceBin, err.Error())
 		}
 
 		nonZero := false
@@ -714,21 +894,21 @@ func (image *Image) generateV1(loader *Image) error {
 	for {
 		cnt, err := binFile.Read(dataBuf)
 		if err != nil && err != io.EOF {
-			return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s",
-				image.SourceBin, err.Error()))
+			return util.FmtNewtError(
+				"Failed to read from %s: %s", image.SourceBin, err.Error())
 		}
 		if cnt == 0 {
 			break
 		}
 		_, err = imgFile.Write(dataBuf[0:cnt])
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to write to %s: %s",
-				image.TargetImg, err.Error()))
+			return util.FmtNewtError(
+				"Failed to write to %s: %s", image.TargetImg, err.Error())
 		}
 		_, err = hash.Write(dataBuf[0:cnt])
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s",
-				err.Error()))
+			return util.FmtNewtError(
+				"Failed to hash data: %s", err.Error())
 		}
 	}
 
@@ -744,92 +924,23 @@ func (image *Image) generateV1(loader *Image) error {
 	}
 	err = binary.Write(imgFile, binary.LittleEndian, tlv)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-			"trailer: %s", err.Error()))
+		return util.FmtNewtError(
+			"Failed to serialize image trailer: %s", err.Error())
 	}
 	_, err = imgFile.Write(image.Hash)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to append hash: %s",
-			err.Error()))
-	}
-
-	if image.SigningRSA != nil {
-		/*
-		 * If signing key was set, generate TLV for that.
-		 */
-		tlv := &ImageTrailerTlv{
-			Type: IMAGEv1_TLV_RSA2048,
-			Pad:  0,
-			Len:  256, /* 2048 bits */
-		}
-		var signature []byte
-		if UseRsaPss {
-			opts := rsa.PSSOptions{
-				SaltLength: rsa.PSSSaltLengthEqualsHash,
-			}
-			signature, err = rsa.SignPSS(rand.Reader, image.SigningRSA,
-				crypto.SHA256, image.Hash, &opts)
-		} else {
-			signature, err = rsa.SignPKCS1v15(rand.Reader, image.SigningRSA,
-				crypto.SHA256, image.Hash)
-		}
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf(
-				"Failed to compute signature: %s", err))
-		}
-
-		err = binary.Write(imgFile, binary.LittleEndian, tlv)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-				"trailer: %s", err.Error()))
-		}
-		_, err = imgFile.Write(signature)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s",
-				err.Error()))
-		}
+		return util.FmtNewtError(
+			"Failed to append hash: %s", err.Error())
 	}
-	if image.SigningEC != nil {
-		r, s, err := ecdsa.Sign(rand.Reader, image.SigningEC, image.Hash)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf(
-				"Failed to compute signature: %s", err))
-		}
-
-		sigLen := image.sigLen()
 
-		var ECDSA ECDSASig
-		ECDSA.R = r
-		ECDSA.S = s
-		signature, err := asn1.Marshal(ECDSA)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf(
-				"Failed to construct signature: %s", err))
-		}
-		if len(signature) > int(sigLen) {
-			return util.NewNewtError(fmt.Sprintf(
-				"Something is really wrong\n"))
-		}
-		tlv := &ImageTrailerTlv{
-			Type: image.sigTlvTypeV1(),
-			Pad:  0,
-			Len:  sigLen,
-		}
-		err = binary.Write(imgFile, binary.LittleEndian, tlv)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-				"trailer: %s", err.Error()))
-		}
-		_, err = imgFile.Write(signature)
+	if len(image.Keys) > 0 {
+		tlvBytes, err := generateSigTlv(image.Keys[0], image.Hash)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s",
-				err.Error()))
+			return err
 		}
-		pad := make([]byte, int(sigLen)-len(signature))
-		_, err = imgFile.Write(pad)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-				"trailer: %s", err.Error()))
+		if _, err := imgFile.Write(tlvBytes); err != nil {
+			return util.FmtNewtError(
+				"Failed to append sig TLV: %s", err.Error())
 		}
 	}
 
@@ -851,22 +962,21 @@ func (image *Image) generateV1(loader *Image) error {
 func (image *Image) generateV2(loader *Image) error {
 	binFile, err := os.Open(image.SourceBin)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't open app binary: %s",
-			err.Error()))
+		return util.FmtNewtError("Can't open app binary: %s", err.Error())
 	}
 	defer binFile.Close()
 
 	binInfo, err := binFile.Stat()
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't stat app binary %s: %s",
-			image.SourceBin, err.Error()))
+		return util.FmtNewtError("Can't stat app binary %s: %s",
+			image.SourceBin, err.Error())
 	}
 
 	imgFile, err := os.OpenFile(image.TargetImg,
 		os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Can't open target image %s: %s",
-			image.TargetImg, err.Error()))
+		return util.FmtNewtError("Can't open target image %s: %s",
+			image.TargetImg, err.Error())
 	}
 	defer imgFile.Close()
 
@@ -876,12 +986,12 @@ func (image *Image) generateV2(loader *Image) error {
 	if PubKeyFile != "" {
 		_, err = rand.Read(plainSecret)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Random generation error: %s\n", err))
+			return util.FmtNewtError("Random generation error: %s\n", err)
 		}
 
 		keyBytes, err := ioutil.ReadFile(PubKeyFile)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Error reading pubkey file: %s", err))
+			return util.FmtNewtError("Error reading pubkey file: %s", err)
 		}
 
 		// Try reading as PEM (asymetric key), if it fails, assume this is a
@@ -890,26 +1000,26 @@ func (image *Image) generateV2(loader *Image) error {
 		if b == nil {
 			kek, err := base64.StdEncoding.DecodeString(string(keyBytes))
 			if err != nil {
-				return util.NewNewtError(fmt.Sprintf("Error decoding kek: %s", err))
+				return util.FmtNewtError("Error decoding kek: %s", err)
 			} else if len(kek) != 16 {
-				return util.NewNewtError(fmt.Sprintf("Unexpected key size: %d != 16", len(kek)))
+				return util.FmtNewtError("Unexpected key size: %d != 16", len(kek))
 			}
 
 			cipher, err := aes.NewCipher(kek)
 			if err != nil {
-				return util.NewNewtError(fmt.Sprintf("Error creating keywrap cipher: %s", err))
+				return util.FmtNewtError("Error creating keywrap cipher: %s", err)
 			}
 
 			cipherSecret, err = keywrap.Wrap(cipher, plainSecret)
 			if err != nil {
-				return util.NewNewtError(fmt.Sprintf("Error key-wrapping: %s", err))
+				return util.FmtNewtError("Error key-wrapping: %s", err)
 			}
 		} else if b.Type != "PUBLIC KEY" && b.Type != "RSA PUBLIC KEY" {
 			return util.NewNewtError("Invalid PEM file")
 		} else {
 			pub, err := x509.ParsePKIXPublicKey(b.Bytes)
 			if err != nil {
-				return util.NewNewtError(fmt.Sprintf("Error parsing pubkey file: %s", err))
+				return util.FmtNewtError("Error parsing pubkey file: %s", err)
 			}
 
 			var pubk *rsa.PublicKey
@@ -917,13 +1027,13 @@ func (image *Image) generateV2(loader *Image) error {
 			case *rsa.PublicKey:
 				pubk = pub.(*rsa.PublicKey)
 			default:
-				return util.NewNewtError(fmt.Sprintf("Error parsing pubkey file: %s", err))
+				return util.FmtNewtError("Error parsing pubkey file: %s", err)
 			}
 
 			rng := rand.Reader
 			cipherSecret, err = rsa.EncryptOAEP(sha256.New(), rng, pubk, plainSecret, nil)
 			if err != nil {
-				return util.NewNewtError(fmt.Sprintf("Error from encryption: %s\n", err))
+				return util.FmtNewtError("Error from encryption: %s\n", err)
 			}
 		}
 	}
@@ -936,8 +1046,8 @@ func (image *Image) generateV2(loader *Image) error {
 	if loader != nil {
 		err = binary.Write(hash, binary.LittleEndian, loader.Hash)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to seed hash: %s",
-				err.Error()))
+			return util.FmtNewtError("Failed to seed hash: %s",
+				err.Error())
 		}
 	}
 
@@ -969,8 +1079,8 @@ func (image *Image) generateV2(loader *Image) error {
 		 * the image when it is padded.
 		 */
 		if image.HeaderSize < IMAGE_HEADER_SIZE {
-			return util.NewNewtError(fmt.Sprintf("Image header must be at "+
-				"least %d bytes", IMAGE_HEADER_SIZE))
+			return util.FmtNewtError("Image header must be at "+
+				"least %d bytes", IMAGE_HEADER_SIZE)
 		}
 
 		hdr.HdrSz = uint16(image.HeaderSize)
@@ -978,13 +1088,13 @@ func (image *Image) generateV2(loader *Image) error {
 
 	err = binary.Write(imgFile, binary.LittleEndian, hdr)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s",
-			err.Error()))
+		return util.FmtNewtError("Failed to serialize image hdr: %s",
+			err.Error())
 	}
 	err = binary.Write(hash, binary.LittleEndian, hdr)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s",
-			err.Error()))
+		return util.FmtNewtError("Failed to hash data: %s",
+			err.Error())
 	}
 
 	if image.HeaderSize > IMAGE_HEADER_SIZE {
@@ -996,14 +1106,14 @@ func (image *Image) generateV2(loader *Image) error {
 
 		_, err = imgFile.Write(buf)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to write padding: %s",
-				err.Error()))
+			return util.FmtNewtError("Failed to write padding: %s",
+				err.Error())
 		}
 
 		_, err = hash.Write(buf)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to hash padding: %s",
-				err.Error()))
+			return util.FmtNewtError("Failed to hash padding: %s",
+				err.Error())
 		}
 	}
 
@@ -1014,8 +1124,8 @@ func (image *Image) generateV2(loader *Image) error {
 		buf := make([]byte, image.SrcSkip)
 		_, err = binFile.Read(buf)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s",
-				image.SourceBin, err.Error()))
+			return util.FmtNewtError("Failed to read from %s: %s",
+				image.SourceBin, err.Error())
 		}
 
 		nonZero := false
@@ -1049,16 +1159,16 @@ func (image *Image) generateV2(loader *Image) error {
 	for {
 		cnt, err := binFile.Read(dataBuf)
 		if err != nil && err != io.EOF {
-			return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s",
-				image.SourceBin, err.Error()))
+			return util.FmtNewtError("Failed to read from %s: %s",
+				image.SourceBin, err.Error())
 		}
 		if cnt == 0 {
 			break
 		}
 		_, err = hash.Write(dataBuf[0:cnt])
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s",
-				err.Error()))
+			return util.FmtNewtError("Failed to hash data: %s",
+				err.Error())
 		}
 		if cipherSecret == nil {
 			_, err = imgFile.Write(dataBuf[0:cnt])
@@ -1067,8 +1177,8 @@ func (image *Image) generateV2(loader *Image) error {
 			_, err = imgFile.Write(encBuf[0:cnt])
 		}
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to write to %s: %s",
-				image.TargetImg, err.Error()))
+			return util.FmtNewtError("Failed to write to %s: %s",
+				image.TargetImg, err.Error())
 		}
 	}
 
@@ -1088,8 +1198,8 @@ func (image *Image) generateV2(loader *Image) error {
 	}
 	err = binary.Write(imgFile, binary.LittleEndian, tlvInfo)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s",
-			err.Error()))
+		return util.FmtNewtError("Failed to serialize image hdr: %s",
+			err.Error())
 	}
 
 	/*
@@ -1102,110 +1212,36 @@ func (image *Image) generateV2(loader *Image) error {
 	}
 	err = binary.Write(imgFile, binary.LittleEndian, tlv)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-			"trailer: %s", err.Error()))
+		return util.FmtNewtError("Failed to serialize image "+
+			"trailer: %s", err.Error())
 	}
 	_, err = imgFile.Write(image.Hash)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to append hash: %s",
-			err.Error()))
+		return util.FmtNewtError("Failed to append hash: %s",
+			err.Error())
 	}
 
-	if image.SigningRSA != nil || image.SigningEC != nil {
-		keyHash, err := image.sigKeyHash()
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to compute hash " +
-				"of the public key"))
-		}
+	for _, key := range image.Keys {
+		key.assertValid()
 
-		tlv = &ImageTrailerTlv{
-			Type: IMAGE_TLV_KEYHASH,
-			Pad:  0,
-			Len:  uint16(len(keyHash)),
-		}
-		err = binary.Write(imgFile, binary.LittleEndian, tlv)
+		tlvBytes, err := generateKeyHashTlv(key)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serial image "+
-				"trailer: %s", err.Error()))
-		}
-		_, err = imgFile.Write(keyHash)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to append "+
-				"key hash: %s", err.Error()))
-		}
-	}
-	if image.SigningRSA != nil {
-		/*
-		 * If signing key was set, generate TLV for that.
-		 */
-		tlv := &ImageTrailerTlv{
-			Type: IMAGE_TLV_RSA2048,
-			Pad:  0,
-			Len:  256, /* 2048 bits */
-		}
-		var signature []byte
-		opts := rsa.PSSOptions{
-			SaltLength: rsa.PSSSaltLengthEqualsHash,
-		}
-		signature, err = rsa.SignPSS(rand.Reader, image.SigningRSA,
-			crypto.SHA256, image.Hash, &opts)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf(
-				"Failed to compute signature: %s", err))
+			return err
 		}
 
-		err = binary.Write(imgFile, binary.LittleEndian, tlv)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-				"trailer: %s", err.Error()))
+		if _, err = imgFile.Write(tlvBytes); err != nil {
+			return util.FmtNewtError(
+				"Failed to append key hash: %s", err.Error())
 		}
-		_, err = imgFile.Write(signature)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s",
-				err.Error()))
-		}
-	}
-	if image.SigningEC != nil {
-		r, s, err := ecdsa.Sign(rand.Reader, image.SigningEC, image.Hash)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf(
-				"Failed to compute signature: %s", err))
-		}
-
-		sigLen := image.sigLen()
 
-		var ECDSA ECDSASig
-		ECDSA.R = r
-		ECDSA.S = s
-		signature, err := asn1.Marshal(ECDSA)
+		tlvBytes, err = generateSigTlv(key, image.Hash)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf(
-				"Failed to construct signature: %s", err))
+			return err
 		}
-		if len(signature) > int(sigLen) {
-			return util.NewNewtError(fmt.Sprintf(
-				"Something is really wrong\n"))
-		}
-		tlv := &ImageTrailerTlv{
-			Type: image.sigTlvType(),
-			Pad:  0,
-			Len:  sigLen,
-		}
-		err = binary.Write(imgFile, binary.LittleEndian, tlv)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-				"trailer: %s", err.Error()))
-		}
-		_, err = imgFile.Write(signature)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s",
-				err.Error()))
-		}
-		pad := make([]byte, int(sigLen)-len(signature))
-		_, err = imgFile.Write(pad)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-				"trailer: %s", err.Error()))
+
+		if _, err = imgFile.Write(tlvBytes); err != nil {
+			return util.FmtNewtError(
+				"Failed to append signature: %s", err.Error())
 		}
 	}
 
@@ -1215,22 +1251,20 @@ func (image *Image) generateV2(loader *Image) error {
 		} else if len(cipherSecret) == 24 {
 			_type = IMAGE_TLV_ENC_KEK
 		} else {
-			return util.NewNewtError(fmt.Sprintf("Invalid enc TLV size "))
+			return util.FmtNewtError("Invalid enc TLV size ")
 		}
 		tlv := &ImageTrailerTlv{
 			Type: _type,
 			Pad:  0,
 			Len:  uint16(len(cipherSecret)),
 		}
-		err = binary.Write(imgFile, binary.LittleEndian, tlv)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
-				"trailer: %s", err.Error()))
+		if err := binary.Write(imgFile, binary.LittleEndian, tlv); err != nil {
+			return util.FmtNewtError(
+				"Failed to serialize cipher secret TLV: %s", err.Error())
 		}
-		_, err = imgFile.Write(cipherSecret)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Failed to append encrypted key: %s",
-				err.Error()))
+		if _, err := imgFile.Write(cipherSecret); err != nil {
+			return util.FmtNewtError("Failed to append encrypted key: %s",
+				err.Error())
 		}
 	}
 
@@ -1258,8 +1292,8 @@ func (image *Image) generateV2(loader *Image) error {
 	}
 	err = binary.Write(imgFile, binary.LittleEndian, tlvInfo)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s",
-			err.Error()))
+		return util.FmtNewtError("Failed to serialize image hdr: %s",
+			err.Error())
 	}
 
 	return nil


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services