You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2019/01/04 18:21:07 UTC
[mynewt-newt] 02/17: Remove the `flash` and `image` packages
This is an automated email from the ASF dual-hosted git repository.
ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git
commit cf572b687eabd989520219be59b2eb3a064e498b
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Tue Nov 20 17:50:16 2018 -0800
Remove the `flash` and `image` packages
This functionality is now implemented in the "artifact" library.
---
newt/flash/flash.go | 421 --------------
newt/image/encrypted.go | 196 -------
newt/image/image.go | 1463 -----------------------------------------------
newt/image/keys_test.go | 246 --------
4 files changed, 2326 deletions(-)
diff --git a/newt/flash/flash.go b/newt/flash/flash.go
deleted file mode 100644
index 97114c5..0000000
--- a/newt/flash/flash.go
+++ /dev/null
@@ -1,421 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package flash
-
-import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "sort"
- "strings"
-
- log "github.com/Sirupsen/logrus"
- "github.com/spf13/cast"
-
- "mynewt.apache.org/newt/newt/newtutil"
- "mynewt.apache.org/newt/util"
-)
-
-const FLASH_AREA_NAME_BOOTLOADER = "FLASH_AREA_BOOTLOADER"
-const FLASH_AREA_NAME_IMAGE_0 = "FLASH_AREA_IMAGE_0"
-const FLASH_AREA_NAME_IMAGE_1 = "FLASH_AREA_IMAGE_1"
-const FLASH_AREA_NAME_IMAGE_SCRATCH = "FLASH_AREA_IMAGE_SCRATCH"
-
-var SYSTEM_AREA_NAME_ID_MAP = map[string]int{
- FLASH_AREA_NAME_BOOTLOADER: 0,
- FLASH_AREA_NAME_IMAGE_0: 1,
- FLASH_AREA_NAME_IMAGE_1: 2,
- FLASH_AREA_NAME_IMAGE_SCRATCH: 3,
-}
-
-const AREA_USER_ID_MIN = 16
-
-const HEADER_PATH = "sysflash/sysflash.h"
-const C_VAR_NAME = "sysflash_map_dflt"
-const C_VAR_COMMENT = `/**
- * This flash map definition is used for two purposes:
- * 1. To locate the meta area, which contains the true flash map definition.
- * 2. As a fallback in case the meta area cannot be read from flash.
- */
-`
-
-type FlashArea struct {
- Name string
- Id int
- Device int
- Offset int
- Size int
-}
-
-type FlashMap struct {
- Areas map[string]FlashArea
- Overlaps [][]FlashArea
- IdConflicts [][]FlashArea
-}
-
-func newFlashMap() FlashMap {
- return FlashMap{
- Areas: map[string]FlashArea{},
- Overlaps: [][]FlashArea{},
- }
-}
-
-func flashAreaErr(areaName string, format string, args ...interface{}) error {
- return util.NewNewtError(
- "failure while parsing flash area \"" + areaName + "\": " +
- fmt.Sprintf(format, args...))
-}
-
-func parseSize(val string) (int, error) {
- lower := strings.ToLower(val)
-
- multiplier := 1
- if strings.HasSuffix(lower, "kb") {
- multiplier = 1024
- lower = strings.TrimSuffix(lower, "kb")
- }
-
- num, err := util.AtoiNoOct(lower)
- if err != nil {
- return 0, err
- }
-
- return num * multiplier, nil
-}
-
-func parseFlashArea(
- name string, ymlFields map[string]interface{}) (FlashArea, error) {
-
- area := FlashArea{
- Name: name,
- }
-
- idPresent := false
- devicePresent := false
- offsetPresent := false
- sizePresent := false
-
- var isSystem bool
- area.Id, isSystem = SYSTEM_AREA_NAME_ID_MAP[name]
-
- var err error
-
- fields := cast.ToStringMapString(ymlFields)
- for k, v := range fields {
- switch k {
- case "user_id":
- if isSystem {
- return area, flashAreaErr(name,
- "system areas cannot specify a user ID")
- }
- userId, err := util.AtoiNoOct(v)
- if err != nil {
- return area, flashAreaErr(name, "invalid user id: %s", v)
- }
- area.Id = userId + AREA_USER_ID_MIN
- idPresent = true
-
- case "device":
- area.Device, err = util.AtoiNoOct(v)
- if err != nil {
- return area, flashAreaErr(name, "invalid device: %s", v)
- }
- devicePresent = true
-
- case "offset":
- area.Offset, err = util.AtoiNoOct(v)
- if err != nil {
- return area, flashAreaErr(name, "invalid offset: %s", v)
- }
- offsetPresent = true
-
- case "size":
- area.Size, err = parseSize(v)
- if err != nil {
- return area, flashAreaErr(name, err.Error())
- }
- sizePresent = true
-
- default:
- util.StatusMessage(util.VERBOSITY_QUIET,
- "Warning: flash area \"%s\" contains unrecognized field: %s",
- name, k)
- }
- }
-
- if !isSystem && !idPresent {
- return area, flashAreaErr(name, "required field \"user_id\" missing")
- }
- if !devicePresent {
- return area, flashAreaErr(name, "required field \"device\" missing")
- }
- if !offsetPresent {
- return area, flashAreaErr(name, "required field \"offset\" missing")
- }
- if !sizePresent {
- return area, flashAreaErr(name, "required field \"size\" missing")
- }
-
- return area, nil
-}
-
-func (flashMap FlashMap) unSortedAreas() []FlashArea {
- areas := make([]FlashArea, 0, len(flashMap.Areas))
- for _, area := range flashMap.Areas {
- areas = append(areas, area)
- }
-
- return areas
-}
-
-func (flashMap FlashMap) SortedAreas() []FlashArea {
- idMap := make(map[int]FlashArea, len(flashMap.Areas))
- ids := make([]int, 0, len(flashMap.Areas))
- for _, area := range flashMap.Areas {
- idMap[area.Id] = area
- ids = append(ids, area.Id)
- }
- sort.Ints(ids)
-
- areas := make([]FlashArea, len(ids))
- for i, id := range ids {
- areas[i] = idMap[id]
- }
-
- return areas
-}
-
-func (flashMap FlashMap) DeviceIds() []int {
- deviceMap := map[int]struct{}{}
-
- for _, area := range flashMap.Areas {
- deviceMap[area.Device] = struct{}{}
- }
-
- devices := make([]int, 0, len(deviceMap))
- for device, _ := range deviceMap {
- devices = append(devices, device)
- }
- sort.Ints(devices)
-
- return devices
-}
-
-func areasDistinct(a FlashArea, b FlashArea) bool {
- var lo FlashArea
- var hi FlashArea
-
- if a.Offset < b.Offset {
- lo = a
- hi = b
- } else {
- lo = b
- hi = a
- }
-
- return lo.Device != hi.Device || lo.Offset+lo.Size <= hi.Offset
-}
-
-func (flashMap *FlashMap) detectOverlaps() {
- flashMap.Overlaps = [][]FlashArea{}
-
- // Convert the map to a slice.
- areas := flashMap.unSortedAreas()
-
- for i := 0; i < len(areas)-1; i++ {
- iarea := areas[i]
- for j := i + 1; j < len(areas); j++ {
- jarea := areas[j]
-
- if !areasDistinct(iarea, jarea) {
- flashMap.Overlaps = append(
- flashMap.Overlaps, []FlashArea{iarea, jarea})
- }
-
- if iarea.Id == jarea.Id {
- flashMap.IdConflicts = append(
- flashMap.IdConflicts, []FlashArea{iarea, jarea})
- }
- }
- }
-}
-
-func (flashMap FlashMap) ErrorText() string {
- str := ""
-
- if len(flashMap.IdConflicts) > 0 {
- str += "Conflicting flash area IDs detected:\n"
-
- for _, pair := range flashMap.IdConflicts {
- str += fmt.Sprintf(" (%d) %s =/= %s\n",
- pair[0].Id-AREA_USER_ID_MIN, pair[0].Name, pair[1].Name)
- }
- }
-
- if len(flashMap.Overlaps) > 0 {
- str += "Overlapping flash areas detected:\n"
-
- for _, pair := range flashMap.Overlaps {
- str += fmt.Sprintf(" %s =/= %s\n", pair[0].Name, pair[1].Name)
- }
- }
-
- return str
-}
-
-func Read(ymlFlashMap map[string]interface{}) (FlashMap, error) {
- flashMap := newFlashMap()
-
- ymlAreas := ymlFlashMap["areas"]
- if ymlAreas == nil {
- return flashMap, util.NewNewtError(
- "\"areas\" mapping missing from flash map definition")
- }
-
- areaMap := cast.ToStringMap(ymlAreas)
- for k, v := range areaMap {
- if _, ok := flashMap.Areas[k]; ok {
- return flashMap, flashAreaErr(k, "name conflict")
- }
-
- ymlArea := cast.ToStringMap(v)
- area, err := parseFlashArea(k, ymlArea)
- if err != nil {
- return flashMap, flashAreaErr(k, err.Error())
- }
-
- flashMap.Areas[k] = area
- }
-
- flashMap.detectOverlaps()
-
- return flashMap, nil
-}
-
-func (flashMap FlashMap) varDecl() string {
- return fmt.Sprintf("const struct flash_area %s[%d]", C_VAR_NAME,
- len(flashMap.Areas))
-}
-
-func (area FlashArea) writeHeader(w io.Writer) {
- fmt.Fprintf(w, "#define %-40s %d\n", area.Name, area.Id)
-}
-
-func (flashMap FlashMap) writeHeader(w io.Writer) {
- fmt.Fprintf(w, newtutil.GeneratedPreamble())
-
- fmt.Fprintf(w, "#ifndef H_MYNEWT_SYSFLASH_\n")
- fmt.Fprintf(w, "#define H_MYNEWT_SYSFLASH_\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, "#include \"flash_map/flash_map.h\"\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, "%s", C_VAR_COMMENT)
- fmt.Fprintf(w, "extern %s;\n", flashMap.varDecl())
- fmt.Fprintf(w, "\n")
-
- for _, area := range flashMap.SortedAreas() {
- area.writeHeader(w)
- }
-
- fmt.Fprintf(w, "\n#endif\n")
-}
-
-func sizeComment(size int) string {
- if size%1024 != 0 {
- return ""
- }
-
- return fmt.Sprintf(" /* %d kB */", size/1024)
-}
-
-func (area FlashArea) writeSrc(w io.Writer) {
- fmt.Fprintf(w, " /* %s */\n", area.Name)
- fmt.Fprintf(w, " {\n")
- fmt.Fprintf(w, " .fa_id = %d,\n", area.Id)
- fmt.Fprintf(w, " .fa_device_id = %d,\n", area.Device)
- fmt.Fprintf(w, " .fa_off = 0x%08x,\n", area.Offset)
- fmt.Fprintf(w, " .fa_size = %d,%s\n", area.Size,
- sizeComment(area.Size))
- fmt.Fprintf(w, " },\n")
-}
-
-func (flashMap FlashMap) writeSrc(w io.Writer) {
- fmt.Fprintf(w, newtutil.GeneratedPreamble())
-
- fmt.Fprintf(w, "#include \"%s\"\n", HEADER_PATH)
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, "%s", C_VAR_COMMENT)
- fmt.Fprintf(w, "%s = {", flashMap.varDecl())
-
- for _, area := range flashMap.SortedAreas() {
- fmt.Fprintf(w, "\n")
- area.writeSrc(w)
- }
-
- fmt.Fprintf(w, "};\n")
-}
-
-func (flashMap FlashMap) ensureWrittenGen(path string, contents []byte) error {
- writeReqd, err := util.FileContentsChanged(path, contents)
- if err != nil {
- return err
- }
- if !writeReqd {
- log.Debugf("flash map unchanged; not writing file (%s).", path)
- return nil
- }
-
- log.Debugf("flash map changed; writing file (%s).", path)
-
- if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
- return util.NewNewtError(err.Error())
- }
-
- if err := ioutil.WriteFile(path, contents, 0644); err != nil {
- return util.NewNewtError(err.Error())
- }
-
- return nil
-}
-
-func (flashMap FlashMap) EnsureWritten(
- srcDir string, includeDir string, targetName string) error {
-
- buf := bytes.Buffer{}
- flashMap.writeSrc(&buf)
- if err := flashMap.ensureWrittenGen(
- fmt.Sprintf("%s/%s-sysflash.c", srcDir, targetName),
- buf.Bytes()); err != nil {
-
- return err
- }
-
- buf = bytes.Buffer{}
- flashMap.writeHeader(&buf)
- if err := flashMap.ensureWrittenGen(
- includeDir+"/"+HEADER_PATH, buf.Bytes()); err != nil {
- return err
- }
-
- return nil
-}
diff --git a/newt/image/encrypted.go b/newt/image/encrypted.go
deleted file mode 100644
index 0547e2f..0000000
--- a/newt/image/encrypted.go
+++ /dev/null
@@ -1,196 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// Decoder for PKCS#5 encrypted PKCS#8 private keys.
-package image
-
-import (
- "crypto/aes"
- "crypto/cipher"
- "crypto/sha1"
- "crypto/sha256"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/asn1"
- "fmt"
- "hash"
-
- "golang.org/x/crypto/pbkdf2"
- "golang.org/x/crypto/ssh/terminal"
-)
-
-var (
- oidPbes2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13}
- oidPbkdf2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12}
- oidHmacWithSha1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 7}
- oidHmacWithSha224 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 8}
- oidHmacWithSha256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9}
- oidAes128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
- oidAes256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
-)
-
-// We only support a narrow set of possible key types, namely the type
-// generated by either MCUboot's `imgtool.py` command, or using an
-// OpenSSL command such as:
-//
-// openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 \
-// -aes-256-cbc > keyfile.pem
-//
-// or similar for ECDSA. Specifically, the encryption must be done
-// with PBES2, and PBKDF2, and aes-256-cbc used as the cipher.
-type pkcs5 struct {
- Algo pkix.AlgorithmIdentifier
- Encrypted []byte
-}
-
-// The parameters when the algorithm in pkcs5 is oidPbes2
-type pbes2 struct {
- KeyDerivationFunc pkix.AlgorithmIdentifier
- EncryptionScheme pkix.AlgorithmIdentifier
-}
-
-// Salt is given as a choice, but we will only support the inlined
-// octet string.
-type pbkdf2Param struct {
- Salt []byte
- IterCount int
- HashFunc pkix.AlgorithmIdentifier
- // Optional and default values omitted, and unsupported.
-}
-
-type hashFunc func() hash.Hash
-
-func parseEncryptedPrivateKey(der []byte) (key interface{}, err error) {
- var wrapper pkcs5
- if _, err = asn1.Unmarshal(der, &wrapper); err != nil {
- return nil, err
- }
- if !wrapper.Algo.Algorithm.Equal(oidPbes2) {
- return nil, fmt.Errorf("pkcs5: Unknown PKCS#5 wrapper algorithm: %v", wrapper.Algo.Algorithm)
- }
-
- var pbparm pbes2
- if _, err = asn1.Unmarshal(wrapper.Algo.Parameters.FullBytes, &pbparm); err != nil {
- return nil, err
- }
- if !pbparm.KeyDerivationFunc.Algorithm.Equal(oidPbkdf2) {
- return nil, fmt.Errorf("pkcs5: Unknown KDF: %v", pbparm.KeyDerivationFunc.Algorithm)
- }
-
- var kdfParam pbkdf2Param
- if _, err = asn1.Unmarshal(pbparm.KeyDerivationFunc.Parameters.FullBytes, &kdfParam); err != nil {
- return nil, err
- }
-
- var hashNew hashFunc
- switch {
- case kdfParam.HashFunc.Algorithm.Equal(oidHmacWithSha1):
- hashNew = sha1.New
- case kdfParam.HashFunc.Algorithm.Equal(oidHmacWithSha224):
- hashNew = sha256.New224
- case kdfParam.HashFunc.Algorithm.Equal(oidHmacWithSha256):
- hashNew = sha256.New
- default:
- return nil, fmt.Errorf("pkcs5: Unsupported hash: %v", pbparm.EncryptionScheme.Algorithm)
- }
-
- // Get the encryption used.
- size := 0
- var iv []byte
- switch {
- case pbparm.EncryptionScheme.Algorithm.Equal(oidAes256CBC):
- size = 32
- if _, err = asn1.Unmarshal(pbparm.EncryptionScheme.Parameters.FullBytes, &iv); err != nil {
- return nil, err
- }
- case pbparm.EncryptionScheme.Algorithm.Equal(oidAes128CBC):
- size = 16
- if _, err = asn1.Unmarshal(pbparm.EncryptionScheme.Parameters.FullBytes, &iv); err != nil {
- return nil, err
- }
- default:
- return nil, fmt.Errorf("pkcs5: Unsupported cipher: %v", pbparm.EncryptionScheme.Algorithm)
- }
-
- return unwrapPbes2Pbkdf2(&kdfParam, size, iv, hashNew, wrapper.Encrypted)
-}
-
-func unwrapPbes2Pbkdf2(param *pbkdf2Param, size int, iv []byte, hashNew hashFunc, encrypted []byte) (key interface{}, err error) {
- pass, err := getPassword()
- if err != nil {
- return nil, err
- }
- cryptoKey := pbkdf2.Key(pass, param.Salt, param.IterCount, size, hashNew)
-
- block, err := aes.NewCipher(cryptoKey)
- if err != nil {
- return nil, err
- }
- enc := cipher.NewCBCDecrypter(block, iv)
-
- plain := make([]byte, len(encrypted))
- enc.CryptBlocks(plain, encrypted)
-
- plain, err = checkPkcs7Padding(plain)
- if err != nil {
- return nil, err
- }
-
- return x509.ParsePKCS8PrivateKey(plain)
-}
-
-// Verify that PKCS#7 padding is correct on this plaintext message.
-// Returns a new slice with the padding removed.
-func checkPkcs7Padding(buf []byte) ([]byte, error) {
- if len(buf) < 16 {
- return nil, fmt.Errorf("Invalid padded buffer")
- }
-
- padLen := int(buf[len(buf)-1])
- if padLen < 1 || padLen > 16 {
- return nil, fmt.Errorf("Invalid padded buffer")
- }
-
- if padLen > len(buf) {
- return nil, fmt.Errorf("Invalid padded buffer")
- }
-
- for pos := len(buf) - padLen; pos < len(buf); pos++ {
- if int(buf[pos]) != padLen {
- return nil, fmt.Errorf("Invalid padded buffer")
- }
- }
-
- return buf[:len(buf)-padLen], nil
-}
-
-// For testing, a key can be set here. If this is empty, the key will
-// be queried via prompt.
-var KeyPassword = []byte{}
-
-// Prompt the user for a password, unless we have stored one for
-// testing.
-func getPassword() ([]byte, error) {
- if len(KeyPassword) != 0 {
- return KeyPassword, nil
- }
-
- fmt.Printf("key password: ")
- return terminal.ReadPassword(0)
-}
diff --git a/newt/image/image.go b/newt/image/image.go
deleted file mode 100644
index 278804e..0000000
--- a/newt/image/image.go
+++ /dev/null
@@ -1,1463 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package image
-
-import (
- "bytes"
- "crypto"
- "crypto/aes"
- "crypto/cipher"
- "crypto/ecdsa"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha256"
- "crypto/x509"
- "encoding/asn1"
- "encoding/base64"
- "encoding/binary"
- "encoding/hex"
- "encoding/pem"
- "fmt"
- "io"
- "io/ioutil"
- "math/big"
- "os"
- "sort"
- "strconv"
- "strings"
-
- keywrap "github.com/NickBall/go-aes-key-wrap"
- log "github.com/Sirupsen/logrus"
-
- "mynewt.apache.org/newt/newt/pkg"
- "mynewt.apache.org/newt/util"
-)
-
-// Set this to enable RSA-PSS for RSA signatures, instead of PKCS#1
-// v1.5. Eventually, this should be the default.
-var UseRsaPss = false
-
-// Use old image format
-var UseV1 = false
-
-// Public key file to encrypt image
-var PubKeyFile = ""
-
-type ImageVersion struct {
- Major uint8
- Minor uint8
- Rev uint16
- 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
- Keys []ImageKey
- KeyId uint8
- Hash []byte
- SrcSkip uint // Number of bytes to skip from the source image.
- HeaderSize uint // If non-zero pad out the header to this size.
- TotalSize uint // Total size, in bytes, of the generated .img file.
-}
-
-type ImageHdrV1 struct {
- Magic uint32
- TlvSz uint16
- KeyId uint8
- Pad1 uint8
- HdrSz uint16
- Pad2 uint16
- ImgSz uint32
- Flags uint32
- Vers ImageVersion
- Pad3 uint32
-}
-
-type ImageHdr struct {
- Magic uint32
- Pad1 uint32
- HdrSz uint16
- Pad2 uint16
- ImgSz uint32
- Flags uint32
- Vers ImageVersion
- Pad3 uint32
-}
-
-type ImageTlvInfo struct {
- Magic uint16
- TlvTotLen uint16
-}
-
-type ImageTrailerTlv struct {
- Type uint8
- Pad uint8
- Len uint16
-}
-
-const (
- IMAGEv1_MAGIC = 0x96f3b83c /* Image header magic */
- IMAGE_MAGIC = 0x96f3b83d /* Image header magic */
- IMAGE_TRAILER_MAGIC = 0x6907 /* Image tlv info magic */
-)
-
-const (
- IMAGE_HEADER_SIZE = 32
-)
-
-/*
- * Image header flags.
- */
-const (
- IMAGEv1_F_PIC = 0x00000001
- IMAGEv1_F_SHA256 = 0x00000002 /* Image contains hash TLV */
- IMAGEv1_F_PKCS15_RSA2048_SHA256 = 0x00000004 /* PKCS15 w/RSA2048 and SHA256 */
- IMAGEv1_F_ECDSA224_SHA256 = 0x00000008 /* ECDSA224 over SHA256 */
- IMAGEv1_F_NON_BOOTABLE = 0x00000010 /* non bootable image */
- IMAGEv1_F_ECDSA256_SHA256 = 0x00000020 /* ECDSA256 over SHA256 */
- IMAGEv1_F_PKCS1_PSS_RSA2048_SHA256 = 0x00000040 /* RSA-PSS w/RSA2048 and SHA256 */
-
- IMAGE_F_PIC = 0x00000001
- IMAGE_F_NON_BOOTABLE = 0x00000002 /* non bootable image */
- IMAGE_F_ENCRYPTED = 0x00000004 /* encrypted image */
-)
-
-/*
- * Image trailer TLV types.
- */
-const (
- IMAGEv1_TLV_SHA256 = 1
- IMAGEv1_TLV_RSA2048 = 2
- IMAGEv1_TLV_ECDSA224 = 3
- IMAGEv1_TLV_ECDSA256 = 4
-
- IMAGE_TLV_KEYHASH = 0x01
- IMAGE_TLV_SHA256 = 0x10
- IMAGE_TLV_RSA2048 = 0x20
- IMAGE_TLV_ECDSA224 = 0x21
- IMAGE_TLV_ECDSA256 = 0x22
- IMAGE_TLV_ENC_RSA = 0x30
- IMAGE_TLV_ENC_KEK = 0x31
-)
-
-/*
- * Data that's going to go to build manifest file
- */
-type ImageManifestSizeArea struct {
- Name string `json:"name"`
- Size uint32 `json:"size"`
-}
-
-type ImageManifestSizeSym struct {
- Name string `json:"name"`
- Areas []*ImageManifestSizeArea `json:"areas"`
-}
-
-type ImageManifestSizeFile struct {
- Name string `json:"name"`
- Syms []*ImageManifestSizeSym `json:"sym"`
-}
-
-type ImageManifestSizePkg struct {
- Name string `json:"name"`
- Files []*ImageManifestSizeFile `json:"files"`
-}
-
-type ImageManifestSizeCollector struct {
- Pkgs []*ImageManifestSizePkg
-}
-
-type ImageManifest struct {
- Name string `json:"name"`
- Date string `json:"build_time"`
- Version string `json:"build_version"`
- BuildID string `json:"id"`
- Image string `json:"image"`
- ImageHash string `json:"image_hash"`
- Loader string `json:"loader"`
- LoaderHash string `json:"loader_hash"`
- Pkgs []*ImageManifestPkg `json:"pkgs"`
- LoaderPkgs []*ImageManifestPkg `json:"loader_pkgs,omitempty"`
- TgtVars []string `json:"target"`
- Repos []ImageManifestRepo `json:"repos"`
-
- PkgSizes []*ImageManifestSizePkg `json:"pkgsz"`
- LoaderPkgSizes []*ImageManifestSizePkg `json:"loader_pkgsz,omitempty"`
-}
-
-type ImageManifestPkg struct {
- Name string `json:"name"`
- Repo string `json:"repo"`
-}
-
-type ImageManifestRepo struct {
- Name string `json:"name"`
- Commit string `json:"commit"`
- Dirty bool `json:"dirty,omitempty"`
- URL string `json:"url,omitempty"`
-}
-
-type RepoManager struct {
- repos map[string]ImageManifestRepo
-}
-
-type ECDSASig struct {
- R *big.Int
- S *big.Int
-}
-
-func ParseVersion(versStr string) (ImageVersion, error) {
- var err error
- var major uint64
- var minor uint64
- var rev uint64
- var buildNum uint64
- var ver ImageVersion
-
- components := strings.Split(versStr, ".")
- major, err = strconv.ParseUint(components[0], 10, 8)
- if err != nil {
- return ver, util.FmtNewtError("Invalid version string %s", versStr)
- }
- if len(components) > 1 {
- minor, err = strconv.ParseUint(components[1], 10, 8)
- if err != nil {
- return ver, util.FmtNewtError("Invalid version string %s", versStr)
- }
- }
- if len(components) > 2 {
- rev, err = strconv.ParseUint(components[2], 10, 16)
- if err != nil {
- return ver, util.FmtNewtError("Invalid version string %s", versStr)
- }
- }
- if len(components) > 3 {
- buildNum, err = strconv.ParseUint(components[3], 10, 32)
- if err != nil {
- return ver, util.FmtNewtError("Invalid version string %s", versStr)
- }
- }
-
- ver.Major = uint8(major)
- ver.Minor = uint8(minor)
- ver.Rev = uint16(rev)
- ver.BuildNum = uint32(buildNum)
- return ver, nil
-}
-
-func (ver ImageVersion) String() string {
- return fmt.Sprintf("%d.%d.%d.%d",
- ver.Major, ver.Minor, ver.Rev, ver.BuildNum)
-}
-
-func NewImage(srcBinPath string, dstImgPath string) (*Image, error) {
- image := &Image{}
-
- image.SourceBin = srcBinPath
- image.TargetImg = dstImgPath
- return image, nil
-}
-
-func OldImage(imgPath string) (*Image, error) {
- image := &Image{}
-
- image.SourceImg = imgPath
- return image, nil
-}
-
-func (image *Image) SetVersion(versStr string) error {
- ver, err := ParseVersion(versStr)
- if err != nil {
- return err
- }
-
- log.Debugf("Assigning version number %d.%d.%d.%d\n",
- ver.Major, ver.Minor, ver.Rev, ver.BuildNum)
-
- image.Version = ver
-
- buf := new(bytes.Buffer)
- err = binary.Write(buf, binary.LittleEndian, image.Version)
- if err != nil {
- fmt.Printf("Bombing out\n")
- return nil
- }
-
- return nil
-}
-
-func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
- var privKey interface{}
- var err error
-
- block, data := pem.Decode(keyBytes)
- if block != nil && block.Type == "EC PARAMETERS" {
- /*
- * Openssl prepends an EC PARAMETERS block before the
- * key itself. If we see this first, just skip it,
- * and go on to the data block.
- */
- block, _ = pem.Decode(data)
- }
- if block != nil && block.Type == "RSA PRIVATE KEY" {
- /*
- * ParsePKCS1PrivateKey returns an RSA private key from its ASN.1
- * PKCS#1 DER encoded form.
- */
- privKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
- if err != nil {
- return nil, util.FmtNewtError(
- "Private key parsing failed: %s", err)
- }
- }
- if block != nil && block.Type == "EC PRIVATE KEY" {
- /*
- * ParseECPrivateKey returns a EC private key
- */
- privKey, err = x509.ParseECPrivateKey(block.Bytes)
- if err != nil {
- return nil, util.FmtNewtError(
- "Private key parsing failed: %s", err)
- }
- }
- if block != nil && block.Type == "PRIVATE KEY" {
- // This indicates a PKCS#8 unencrypted private key.
- // The particular type of key will be indicated within
- // the key itself.
- privKey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
- if err != nil {
- return nil, util.FmtNewtError(
- "Private key parsing failed: %s", err)
- }
- }
- if block != nil && block.Type == "ENCRYPTED PRIVATE KEY" {
- // This indicates a PKCS#8 key wrapped with PKCS#5
- // encryption.
- privKey, err = parseEncryptedPrivateKey(block.Bytes)
- if err != nil {
- return nil, util.FmtNewtError("Unable to decode encrypted private key: %s", err)
- }
- }
- if privKey == nil {
- return nil, util.NewNewtError("Unknown private key format, EC/RSA private " +
- "key in PEM format only.")
- }
-
- return privKey, nil
-}
-
-func readKey(filename string) (ImageKey, error) {
- key := ImageKey{}
-
- keyBytes, err := ioutil.ReadFile(filename)
- if err != nil {
- return key, util.FmtNewtError("Error reading key file: %s", err)
- }
-
- privKey, err := ParsePrivateKey(keyBytes)
- if err != nil {
- return key, err
- }
-
- switch priv := privKey.(type) {
- case *rsa.PrivateKey:
- key.Rsa = priv
- case *ecdsa.PrivateKey:
- key.Ec = priv
- default:
- 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) 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 {
- 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.FmtNewtError("Unsupported ECC curve")
- }
- }
-}
-
-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 {
- switch key.Ec.Curve.Params().Name {
- case "P-224":
- fallthrough
- case "P-256":
- pubkey, _ := x509.MarshalPKIXPublicKey(&key.Ec.PublicKey)
- sum := sha256.Sum256(pubkey)
- return sum[:4], nil
- default:
- return nil, util.NewNewtError("Unsupported ECC curve")
- }
- }
-}
-
-func (key *ImageKey) sigLen() uint16 {
- key.assertValid()
-
- if key.Rsa != nil {
- return 256
- } else {
- switch key.Ec.Curve.Params().Name {
- case "P-224":
- return 68
- case "P-256":
- return 72
- default:
- return 0
- }
- }
-}
-
-func (key *ImageKey) sigTlvType() uint8 {
- key.assertValid()
-
- 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 {
- 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.FmtNewtError("Can't open image file %s: %s",
- image.SourceImg, err.Error())
- }
-
- srcInfo, err := srcImg.Stat()
- if err != nil {
- return util.FmtNewtError("Can't stat image file %s: %s",
- image.SourceImg, err.Error())
- }
-
- var hdr1 ImageHdrV1
- var hdr2 ImageHdr
- var hdrSz uint16
- var imgSz uint32
-
- err = binary.Read(srcImg, binary.LittleEndian, &hdr1)
- if err == nil {
- srcImg.Seek(0, 0)
- err = binary.Read(srcImg, binary.LittleEndian, &hdr2)
- }
- if err != nil {
- 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.FmtNewtError("File %s is not an image\n",
- image.SourceImg)
- }
- imgSz = hdr1.ImgSz
- hdrSz = hdr1.HdrSz
- image.Version = hdr1.Vers
-
- log.Debugf("Resigning %s (ver %d.%d.%d.%d)", image.SourceImg,
- hdr1.Vers.Major, hdr1.Vers.Minor, hdr1.Vers.Rev,
- hdr1.Vers.BuildNum)
- } else if hdr2.Magic == IMAGE_MAGIC {
- if uint32(srcInfo.Size()) < uint32(hdr2.HdrSz)+hdr2.ImgSz {
- return util.FmtNewtError("File %s is not an image\n",
- image.SourceImg)
- }
- imgSz = hdr2.ImgSz
- hdrSz = hdr2.HdrSz
- image.Version = hdr2.Vers
-
- log.Debugf("Resigning %s (ver %d.%d.%d.%d)", image.SourceImg,
- hdr2.Vers.Major, hdr2.Vers.Minor, hdr2.Vers.Rev,
- hdr2.Vers.BuildNum)
- } else {
- 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.FmtNewtError("Creating temp file failed: %s",
- err.Error())
- }
- tmpBinName := tmpBin.Name()
- defer os.Remove(tmpBinName)
-
- log.Debugf("Extracting data from %s:%d-%d to %s\n",
- image.SourceImg, int64(hdrSz), int64(hdrSz)+int64(imgSz), tmpBinName)
- _, err = io.CopyN(tmpBin, srcImg, int64(imgSz))
- srcImg.Close()
- tmpBin.Close()
- if err != nil {
- return util.FmtNewtError("Cannot copy to tmpfile %s: %s",
- tmpBin.Name(), err.Error())
- }
-
- image.SourceBin = tmpBinName
- image.TargetImg = image.SourceImg
- image.HeaderSize = uint(hdrSz)
-
- 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.FmtNewtError("Can't open app binary: %s",
- err.Error())
- }
- defer binFile.Close()
-
- binInfo, err := binFile.Stat()
- if err != nil {
- 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.FmtNewtError("Can't open target image %s: %s",
- image.TargetImg, err.Error())
- }
- defer imgFile.Close()
-
- /*
- * Compute hash while updating the file.
- */
- hash := sha256.New()
-
- if loader != nil {
- err = binary.Write(hash, binary.LittleEndian, loader.Hash)
- if err != nil {
- return util.FmtNewtError("Failed to seed hash: %s", err.Error())
- }
- }
-
- /*
- * First the header
- */
- hdr := &ImageHdrV1{
- Magic: IMAGEv1_MAGIC,
- TlvSz: 0,
- KeyId: 0,
- Pad1: 0,
- HdrSz: IMAGE_HEADER_SIZE,
- Pad2: 0,
- ImgSz: uint32(binInfo.Size()) - uint32(image.SrcSkip),
- Flags: 0,
- Vers: image.Version,
- Pad3: 0,
- }
-
- 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
- }
-
- hdr.TlvSz += 4 + 32
- hdr.Flags |= IMAGEv1_F_SHA256
-
- if loader != nil {
- hdr.Flags |= IMAGEv1_F_NON_BOOTABLE
- }
-
- if image.HeaderSize != 0 {
- /*
- * Pad the header out to the given size. There will
- * just be zeros between the header and the start of
- * the image when it is padded.
- */
- if image.HeaderSize < IMAGE_HEADER_SIZE {
- return util.FmtNewtError(
- "Image header must be at least %d bytes", IMAGE_HEADER_SIZE)
- }
-
- hdr.HdrSz = uint16(image.HeaderSize)
- }
-
- err = binary.Write(imgFile, binary.LittleEndian, hdr)
- if err != nil {
- return util.FmtNewtError("Failed to serialize image hdr: %s",
- err.Error())
- }
- err = binary.Write(hash, binary.LittleEndian, hdr)
- if err != nil {
- return util.FmtNewtError("Failed to hash data: %s", err.Error())
- }
-
- if image.HeaderSize > IMAGE_HEADER_SIZE {
- /*
- * Pad the image (and hash) with zero bytes to fill
- * out the buffer.
- */
- buf := make([]byte, image.HeaderSize-IMAGE_HEADER_SIZE)
-
- _, err = imgFile.Write(buf)
- if err != nil {
- return util.FmtNewtError(
- "Failed to write padding: %s", err.Error())
- }
-
- _, err = hash.Write(buf)
- if err != nil {
- return util.FmtNewtError("Failed to hash padding: %s", err.Error())
- }
- }
-
- /*
- * Skip requested initial part of image.
- */
- if image.SrcSkip > 0 {
- buf := make([]byte, image.SrcSkip)
- _, err = binFile.Read(buf)
- if err != nil {
- return util.FmtNewtError(
- "Failed to read from %s: %s", image.SourceBin, err.Error())
- }
-
- nonZero := false
- for _, b := range buf {
- if b != 0 {
- nonZero = true
- break
- }
- }
- if nonZero {
- log.Warnf("Skip requested of image %s, but image not preceeded "+
- "by %d bytes of all zeros",
- image.SourceBin, image.SrcSkip)
- }
- }
-
- /*
- * Followed by data.
- */
- dataBuf := make([]byte, 1024)
- for {
- cnt, err := binFile.Read(dataBuf)
- if err != nil && err != io.EOF {
- 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.FmtNewtError(
- "Failed to write to %s: %s", image.TargetImg, err.Error())
- }
- _, err = hash.Write(dataBuf[0:cnt])
- if err != nil {
- return util.FmtNewtError(
- "Failed to hash data: %s", err.Error())
- }
- }
-
- image.Hash = hash.Sum(nil)
-
- /*
- * Trailer with hash of the data
- */
- tlv := &ImageTrailerTlv{
- Type: IMAGEv1_TLV_SHA256,
- Pad: 0,
- Len: uint16(len(image.Hash)),
- }
- err = binary.Write(imgFile, binary.LittleEndian, tlv)
- if err != nil {
- return util.FmtNewtError(
- "Failed to serialize image trailer: %s", err.Error())
- }
- _, err = imgFile.Write(image.Hash)
- if err != nil {
- return util.FmtNewtError(
- "Failed to append hash: %s", err.Error())
- }
-
- if len(image.Keys) > 0 {
- tlvBytes, err := generateSigTlv(image.Keys[0], image.Hash)
- if err != nil {
- return err
- }
- if _, err := imgFile.Write(tlvBytes); err != nil {
- return util.FmtNewtError(
- "Failed to append sig TLV: %s", err.Error())
- }
- }
-
- util.StatusMessage(util.VERBOSITY_VERBOSE,
- "Computed Hash for image %s as %s \n",
- image.TargetImg, hex.EncodeToString(image.Hash))
-
- // XXX: Replace "1" with io.SeekCurrent when go 1.7 becomes mainstream.
- sz, err := imgFile.Seek(0, 1)
- if err != nil {
- return util.FmtNewtError("Failed to calculate file size of generated "+
- "image %s: %s", image.TargetImg, err.Error())
- }
- image.TotalSize = uint(sz)
-
- return nil
-}
-
-func (image *Image) generateV2(loader *Image) error {
- binFile, err := os.Open(image.SourceBin)
- if err != nil {
- return util.FmtNewtError("Can't open app binary: %s", err.Error())
- }
- defer binFile.Close()
-
- binInfo, err := binFile.Stat()
- if err != nil {
- 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.FmtNewtError("Can't open target image %s: %s",
- image.TargetImg, err.Error())
- }
- defer imgFile.Close()
-
- plainSecret := make([]byte, 16)
- var cipherSecret []byte
- var _type uint8
- if PubKeyFile != "" {
- _, err = rand.Read(plainSecret)
- if err != nil {
- return util.FmtNewtError("Random generation error: %s\n", err)
- }
-
- keyBytes, err := ioutil.ReadFile(PubKeyFile)
- if err != nil {
- return util.FmtNewtError("Error reading pubkey file: %s", err)
- }
-
- // Try reading as PEM (asymetric key), if it fails, assume this is a
- // base64 encoded symetric key
- b, _ := pem.Decode(keyBytes)
- if b == nil {
- kek, err := base64.StdEncoding.DecodeString(string(keyBytes))
- if err != nil {
- return util.FmtNewtError("Error decoding kek: %s", err)
- } else if len(kek) != 16 {
- return util.FmtNewtError("Unexpected key size: %d != 16", len(kek))
- }
-
- cipher, err := aes.NewCipher(kek)
- if err != nil {
- return util.FmtNewtError("Error creating keywrap cipher: %s", err)
- }
-
- cipherSecret, err = keywrap.Wrap(cipher, plainSecret)
- if err != nil {
- 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.FmtNewtError("Error parsing pubkey file: %s", err)
- }
-
- var pubk *rsa.PublicKey
- switch pub.(type) {
- case *rsa.PublicKey:
- pubk = pub.(*rsa.PublicKey)
- default:
- 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.FmtNewtError("Error from encryption: %s\n", err)
- }
- }
- }
-
- /*
- * Compute hash while updating the file.
- */
- hash := sha256.New()
-
- if loader != nil {
- err = binary.Write(hash, binary.LittleEndian, loader.Hash)
- if err != nil {
- return util.FmtNewtError("Failed to seed hash: %s",
- err.Error())
- }
- }
-
- /*
- * First the header
- */
- hdr := &ImageHdr{
- Magic: IMAGE_MAGIC,
- Pad1: 0,
- HdrSz: IMAGE_HEADER_SIZE,
- Pad2: 0,
- ImgSz: uint32(binInfo.Size()) - uint32(image.SrcSkip),
- Flags: 0,
- Vers: image.Version,
- Pad3: 0,
- }
-
- if loader != nil {
- hdr.Flags |= IMAGE_F_NON_BOOTABLE
- }
- if cipherSecret != nil {
- hdr.Flags |= IMAGE_F_ENCRYPTED
- }
-
- if image.HeaderSize != 0 {
- /*
- * Pad the header out to the given size. There will
- * just be zeros between the header and the start of
- * the image when it is padded.
- */
- if image.HeaderSize < IMAGE_HEADER_SIZE {
- return util.FmtNewtError("Image header must be at "+
- "least %d bytes", IMAGE_HEADER_SIZE)
- }
-
- hdr.HdrSz = uint16(image.HeaderSize)
- }
-
- err = binary.Write(imgFile, binary.LittleEndian, hdr)
- if err != nil {
- return util.FmtNewtError("Failed to serialize image hdr: %s",
- err.Error())
- }
- err = binary.Write(hash, binary.LittleEndian, hdr)
- if err != nil {
- return util.FmtNewtError("Failed to hash data: %s",
- err.Error())
- }
-
- if image.HeaderSize > IMAGE_HEADER_SIZE {
- /*
- * Pad the image (and hash) with zero bytes to fill
- * out the buffer.
- */
- buf := make([]byte, image.HeaderSize-IMAGE_HEADER_SIZE)
-
- _, err = imgFile.Write(buf)
- if err != nil {
- return util.FmtNewtError("Failed to write padding: %s",
- err.Error())
- }
-
- _, err = hash.Write(buf)
- if err != nil {
- return util.FmtNewtError("Failed to hash padding: %s",
- err.Error())
- }
- }
-
- /*
- * Skip requested initial part of image.
- */
- if image.SrcSkip > 0 {
- buf := make([]byte, image.SrcSkip)
- _, err = binFile.Read(buf)
- if err != nil {
- return util.FmtNewtError("Failed to read from %s: %s",
- image.SourceBin, err.Error())
- }
-
- nonZero := false
- for _, b := range buf {
- if b != 0 {
- nonZero = true
- break
- }
- }
- if nonZero {
- log.Warnf("Skip requested of image %s, but image not preceeded by %d bytes of all zeros",
- image.SourceBin, image.SrcSkip)
- }
- }
-
- var stream cipher.Stream
- if cipherSecret != nil {
- block, err := aes.NewCipher(plainSecret)
- if err != nil {
- return util.NewNewtError("Failed to create block cipher")
- }
- nonce := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
- stream = cipher.NewCTR(block, nonce)
- }
-
- /*
- * Followed by data.
- */
- dataBuf := make([]byte, 16)
- encBuf := make([]byte, 16)
- for {
- cnt, err := binFile.Read(dataBuf)
- if err != nil && err != io.EOF {
- 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.FmtNewtError("Failed to hash data: %s",
- err.Error())
- }
- if cipherSecret == nil {
- _, err = imgFile.Write(dataBuf[0:cnt])
- } else {
- stream.XORKeyStream(encBuf, dataBuf[0:cnt])
- _, err = imgFile.Write(encBuf[0:cnt])
- }
- if err != nil {
- return util.FmtNewtError("Failed to write to %s: %s",
- image.TargetImg, err.Error())
- }
- }
-
- image.Hash = hash.Sum(nil)
-
- /*
- * Write TLV info.
- */
- tlvInfo := &ImageTlvInfo{
- Magic: IMAGE_TRAILER_MAGIC,
- TlvTotLen: 0,
- }
- tlvInfoOff, err := imgFile.Seek(0, 1)
- if err != nil {
- return util.FmtNewtError("Failed to calculate file size of generated "+
- "image %s: %s", image.TargetImg, err.Error())
- }
- err = binary.Write(imgFile, binary.LittleEndian, tlvInfo)
- if err != nil {
- return util.FmtNewtError("Failed to serialize image hdr: %s",
- err.Error())
- }
-
- /*
- * Trailer with hash of the data
- */
- tlv := &ImageTrailerTlv{
- Type: IMAGE_TLV_SHA256,
- Pad: 0,
- Len: uint16(len(image.Hash)),
- }
- err = binary.Write(imgFile, binary.LittleEndian, tlv)
- if err != nil {
- return util.FmtNewtError("Failed to serialize image "+
- "trailer: %s", err.Error())
- }
- _, err = imgFile.Write(image.Hash)
- if err != nil {
- return util.FmtNewtError("Failed to append hash: %s",
- err.Error())
- }
-
- for _, key := range image.Keys {
- key.assertValid()
-
- tlvBytes, err := generateKeyHashTlv(key)
- if err != nil {
- return err
- }
-
- if _, err = imgFile.Write(tlvBytes); err != nil {
- return util.FmtNewtError(
- "Failed to append key hash: %s", err.Error())
- }
-
- tlvBytes, err = generateSigTlv(key, image.Hash)
- if err != nil {
- return err
- }
-
- if _, err = imgFile.Write(tlvBytes); err != nil {
- return util.FmtNewtError(
- "Failed to append signature: %s", err.Error())
- }
- }
-
- if cipherSecret != nil {
- if len(cipherSecret) == 256 {
- _type = IMAGE_TLV_ENC_RSA
- } else if len(cipherSecret) == 24 {
- _type = IMAGE_TLV_ENC_KEK
- } else {
- return util.FmtNewtError("Invalid enc TLV size ")
- }
- tlv := &ImageTrailerTlv{
- Type: _type,
- Pad: 0,
- Len: uint16(len(cipherSecret)),
- }
- if err := binary.Write(imgFile, binary.LittleEndian, tlv); err != nil {
- return util.FmtNewtError(
- "Failed to serialize cipher secret TLV: %s", err.Error())
- }
- if _, err := imgFile.Write(cipherSecret); err != nil {
- return util.FmtNewtError("Failed to append encrypted key: %s",
- err.Error())
- }
- }
-
- util.StatusMessage(util.VERBOSITY_VERBOSE,
- "Computed Hash for image %s as %s \n",
- image.TargetImg, hex.EncodeToString(image.Hash))
-
- // XXX: Replace "1" with io.SeekCurrent when go 1.7 becomes mainstream.
- sz, err := imgFile.Seek(0, 1)
- if err != nil {
- return util.FmtNewtError("Failed to calculate file size of generated "+
- "image %s: %s", image.TargetImg, err.Error())
- }
- image.TotalSize = uint(sz)
-
- tlvInfo.TlvTotLen = uint16(sz - tlvInfoOff)
-
- /*
- * Go back and write tlv info total length
- */
- _, err = imgFile.Seek(tlvInfoOff, 0)
- if err != nil {
- return util.FmtNewtError("Failed to move to tlvInfo offset %d "+
- "image: %s", int(tlvInfoOff), err.Error())
- }
- err = binary.Write(imgFile, binary.LittleEndian, tlvInfo)
- if err != nil {
- return util.FmtNewtError("Failed to serialize image hdr: %s",
- err.Error())
- }
-
- return nil
-}
-
-func (image *Image) Generate(loader *Image) error {
- if UseV1 {
- return image.generateV1(loader)
- } else {
- return image.generateV2(loader)
- }
-}
-
-func CreateBuildId(app *Image, loader *Image) []byte {
- return app.Hash
-}
-
-func NewRepoManager() *RepoManager {
- return &RepoManager{
- repos: make(map[string]ImageManifestRepo),
- }
-}
-
-func (r *RepoManager) GetImageManifestPkg(
- lpkg *pkg.LocalPackage) *ImageManifestPkg {
-
- ip := &ImageManifestPkg{
- Name: lpkg.Name(),
- }
-
- var path string
- if lpkg.Repo().IsLocal() {
- ip.Repo = lpkg.Repo().Name()
- path = lpkg.BasePath()
- } else {
- ip.Repo = lpkg.Repo().Name()
- path = lpkg.BasePath()
- }
-
- if _, present := r.repos[ip.Repo]; present {
- return ip
- }
-
- repo := ImageManifestRepo{
- Name: ip.Repo,
- }
-
- // Make sure we restore the current working dir to whatever it was when
- // this function was called
- cwd, err := os.Getwd()
- if err != nil {
- log.Debugf("Unable to determine current working directory: %v", err)
- return ip
- }
- defer os.Chdir(cwd)
-
- if err := os.Chdir(path); err != nil {
- return ip
- }
-
- var res []byte
-
- res, err = util.ShellCommand([]string{
- "git",
- "rev-parse",
- "HEAD",
- }, nil)
- if err != nil {
- log.Debugf("Unable to determine commit hash for %s: %v", path, err)
- repo.Commit = "UNKNOWN"
- } else {
- repo.Commit = strings.TrimSpace(string(res))
- res, err = util.ShellCommand([]string{
- "git",
- "status",
- "--porcelain",
- }, nil)
- if err != nil {
- log.Debugf("Unable to determine dirty state for %s: %v", path, err)
- } else {
- if len(res) > 0 {
- repo.Dirty = true
- }
- }
- res, err = util.ShellCommand([]string{
- "git",
- "config",
- "--get",
- "remote.origin.url",
- }, nil)
- if err != nil {
- log.Debugf("Unable to determine URL for %s: %v", path, err)
- } else {
- repo.URL = strings.TrimSpace(string(res))
- }
- }
- r.repos[ip.Repo] = repo
-
- return ip
-}
-
-func (r *RepoManager) AllRepos() []ImageManifestRepo {
- keys := make([]string, 0, len(r.repos))
- for k := range r.repos {
- keys = append(keys, k)
- }
-
- sort.Strings(keys)
-
- repos := make([]ImageManifestRepo, 0, len(keys))
- for _, key := range keys {
- repos = append(repos, r.repos[key])
- }
-
- return repos
-}
-
-func NewImageManifestSizeCollector() *ImageManifestSizeCollector {
- return &ImageManifestSizeCollector{}
-}
-
-func (c *ImageManifestSizeCollector) AddPkg(pkg string) *ImageManifestSizePkg {
- p := &ImageManifestSizePkg{
- Name: pkg,
- }
- c.Pkgs = append(c.Pkgs, p)
-
- return p
-}
-
-func (c *ImageManifestSizePkg) AddSymbol(file string, sym string, area string,
- symSz uint32) {
- f := c.addFile(file)
- s := f.addSym(sym)
- s.addArea(area, symSz)
-}
-
-func (p *ImageManifestSizePkg) addFile(file string) *ImageManifestSizeFile {
- for _, f := range p.Files {
- if f.Name == file {
- return f
- }
- }
- f := &ImageManifestSizeFile{
- Name: file,
- }
- p.Files = append(p.Files, f)
-
- return f
-}
-
-func (f *ImageManifestSizeFile) addSym(sym string) *ImageManifestSizeSym {
- s := &ImageManifestSizeSym{
- Name: sym,
- }
- f.Syms = append(f.Syms, s)
-
- return s
-}
-
-func (s *ImageManifestSizeSym) addArea(area string, areaSz uint32) {
- a := &ImageManifestSizeArea{
- Name: area,
- Size: areaSz,
- }
- s.Areas = append(s.Areas, a)
-}
diff --git a/newt/image/keys_test.go b/newt/image/keys_test.go
deleted file mode 100644
index 8612403..0000000
--- a/newt/image/keys_test.go
+++ /dev/null
@@ -1,246 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package image_test
-
-import (
- "io/ioutil"
- "os"
- "path"
- "testing"
-
- "mynewt.apache.org/newt/newt/image"
-)
-
-func TestRSA(t *testing.T) {
- signatureTest(t, rsaPkcs1Private)
-}
-
-func TestPlainRSAPKCS8(t *testing.T) {
- signatureTest(t, rsaPkcs8Private)
-}
-
-func TestEcdsa(t *testing.T) {
- signatureTest(t, ecdsaPrivate)
-}
-
-func TestPlainEcdsaPkcs8(t *testing.T) {
- signatureTest(t, ecdsaPkcs8Private)
-}
-
-func TestEncryptedRSA(t *testing.T) {
- image.KeyPassword = []byte("sample")
- signatureTest(t, rsaEncryptedPrivate)
- image.KeyPassword = []byte{}
-}
-
-func TestEncryptedEcdsa(t *testing.T) {
- image.KeyPassword = []byte("sample")
- signatureTest(t, ecdsaEncryptedPrivate)
- image.KeyPassword = []byte{}
-}
-
-func signatureTest(t *testing.T, privateKey []byte) {
- tmpdir, err := ioutil.TempDir("", "newttest")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tmpdir)
-
- // Create a source image. Format doesn't really matter that
- // much, since the header will be placed on it by the image
- // tool.
-
- simpleName := path.Join(tmpdir, "simple.bin")
- hashedName := path.Join(tmpdir, "simple-hashed.bin")
- signedName := path.Join(tmpdir, "simple-signed.bin")
- keyName := path.Join(tmpdir, "private.pem")
-
- tmp := make([]byte, 256)
- for i := 0; i < len(tmp); i++ {
- tmp[i] = byte(i & 0xFF)
- }
- err = ioutil.WriteFile(simpleName, tmp, 0644)
- if err != nil {
- t.Fatal(err)
- }
-
- img, err := image.NewImage(simpleName, hashedName)
- if err != nil {
- t.Fatal(err)
- }
-
- img.SetVersion("1.5")
- if err != nil {
- t.Fatal(err)
- }
-
- img.Generate(nil)
- if err != nil {
- t.Fatal(err)
- }
-
- // Now try with a signature.
- err = ioutil.WriteFile(keyName, privateKey, 0644)
- if err != nil {
- t.Fatal(err)
- }
-
- img, err = image.NewImage(simpleName, signedName)
- if err != nil {
- t.Fatal(err)
- }
-
- err = img.SetSigningKey(keyName, 0)
- if err != nil {
- t.Fatal(err)
- }
-
- err = img.SetVersion("1.6")
- if err != nil {
- t.Fatal(err)
- }
-
- err = img.Generate(nil)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-// An RSA private key in the old PKCS1 format.
-var rsaPkcs1Private = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA6q2Q/VoFf6U5xm35ynls+HDbHKwfIbBr27PtFJxlS9YT0xKJ
-bcZScPTVizTlft0wfp2TctX/vGd/Y/X3qo5ckRmz+lKUeHm46i4k6rtOBbhBz2id
-hwrO7/ylzwaf8lxn2dj/9ikoYQKFtBb/cKu8wyuvW3gs/ou51AVEF8aKTrl5Expy
-PrhSlh97er2zUmm8NAoo259I5yHK1SvR9kCw2gNXSDQLpFlK2WikdmEbIu0N+cvN
-WM4ONAhffkasznrEOoLPSI66RDrzYhi/Ks9t+N2buEOXao19fDRcSHgZLKT8e6W6
-uK7WxRiEzNbajzgDddbZFqWlcpE7sqPNHFBijwIDAQABAoIBAQDdXx7fLpTzROvM
-F5/C9GnrraGzWVYAlIgZ9o8Umzceo3GN8PV8fND1xq7Novc9he8h8QjPEbksg0Dz
-DWo0FBiTs3hIELAHOWNKXH7sggVmddp2iUvXwEVWsq/CK5CjsbExGXbSQR7a6+Mt
-72fEY+wq+0Fuel2PPETuEI2cE+gRuyspIcO7asmMvLRkxLi2EXU0s4JlqV9UfxKQ
-aqn0PHlRXa5SIzys3mVhXuoe45T50+VKX0DIfu/RuV8njNkkMx74DeEVvf5W4MJW
-vHrRBHoK6KoMrqiwafyPLW/Rh6fMYAdPrffMVuuThtG7Hp83VBVX1HxFhI4Jrf3S
-Hf63hmSZAoGBAO2R/vYBl57qgWEKiMQaU8rzctRbP0TtTsqNdISPMnHV1Tn/rNAU
-m0N7/6IBDb+IlndXDQwIsW/DTXhF2XJSu7n6GXua8B1LF+zuVWUsFfmE3+eLz7B8
-x8G/OkSnOTfRZCYWEoEvzhynn1dlADQ+x49I/XmKqccvAhY71glk6WULAoGBAPzi
-IYo9G+ktlNj9/3OciX7aTCiIIMDyPYtYS6wi59gwH9IswaicHYK4w2fDpTWKlzEE
-18dKF4puuI5GxnKCwHBiWxGhij063cZKKMqA64X41csK+mumux/PAb2gKbGSzzoF
-mSgkKXJ+sZ4ytlgsijEAHV85Sw7j+xy8A0qnCWMNAoGAeCDR7q1hcM8duucrvxWc
-90vg7bZyKLVimROsLneGR3+cAWbiiJlS5W3nFpE31XkItLHE/CfNKTl1i/KuAJwL
-JwBrMFBpSDa3k2v0rGL9fZ2N5rSQwapnC/ZZTWvNiAcOgB+7Ha4BqAWuke+VidWQ
-7Ug4O+Q882Y2xO1ezoNDbX8CgYBq228KyAm8PXuRObsw8iuTg9D8q5ETlwj0kcng
-IhvP2X4IxMrMYbOCompHtX9hIYADwaUgXCmYYHLyA+wlRSTmGFmdGKKefvppqLqV
-32YmhWBp3Oi2hoy5wzJcG4qis4OHZAg00xsEe464Z3tvxNpcHE1NCJuz3hglKzlE
-2VJ5HQKBgQDRisWDbdnOEp7LTXp3Aa33PF1Rx/pkFk4Wb+2Hk977O1OxsAin2cKM
-S5HCltHvON2sCmSQUIxMXXKaNPJiGL3UZJxWZDj38zSg0vO+msmemS1Yjt0xCpbO
-pkl0kvKb/NVlsY4w9kquvql+t9e1rUu9Ug28TKEsSjc9SFrcnVPoNA==
------END RSA PRIVATE KEY-----
-`)
-
-// An RSA private key in PKCS8 format, with no encryption.
-var rsaPkcs8Private = []byte(`-----BEGIN PRIVATE KEY-----
-MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC+FjuXqPSPucsQ
-adxY4nw+9kTgAdsXRIPxq4Q//wkfjEjYhDczN+/rafi0hApuRh7PN7VMGOsDGGR1
-edyertiLt3SfUHAZROIqZ0VAoKGtxgXmnC+s+mMujAv9Ssntbmbi5tNxDcltdWjA
-SdBn7tbIMVVofKaMMugyuXCglxebMm8yxtkSgUvE1E6zZERnteDJTPo8dBCiqkvU
-hf+vG9s1j9lNDMjrZ+d5CHIFmBxJ/WFa6m49lNBFb1Ba43bKdj6mkK05rZ4VWMXU
-evy3Z/UUgU4VPJpoB+GIKy82iOrtjiU7s/6aDkvZ2e+fgxKksN0pzFE9azeA73QS
-bamp28E/AgMBAAECggEBAJ78+4UDFOKt1JF66YkSjjcfRkZSZwyUCwP0oF3ik5/m
-dvtZws29KJevgAyEMDFBxv0srB/k65QgL84uSgATYB2kKRAjeE86VSyASeUfNXui
-GEdlNV8p4hEJo/GMP06uu7FmvU1e6a36uM20L3LuyoiQ8s29DJRQ8/ORNQmstlrg
-J32FZSjTF1mElGPSc1koxhWvl1hE7UGE9pxsSfdsvPNhCIWwAOnVnIv49xG8EWaK
-CkHhEVVdZW8IvO9GYR5U0BJcgzNmdNkS8HVQBIxZtboGAAuPI32EC7siDomKmCF6
-rEcs40f/J/RlK6lrTyKKfqWb4DPtRrOSh9cmjrFFZlECgYEA6mZIANLXJd7CINZ9
-fjotI+FxH8BDOZF7l8xTnOk1e3Me1ia7t2GMcIL+frfG/zMBiDFq0IQuUYScRK1v
-pAILjJKFiU6yY8vH6FZ3mXqiiag6RPa+q89DaUsO0uXRUjQvhtTd5Yy6r8Eac1ya
-y6XC5T5sCJ6HgaF3qlheap+5FkkCgYEAz5qSLShV5oekuj1R0fs+h/Yn7VW9Q0sj
-px8jOD4MWc8gPZ9gZe0UPTvofOLrM3eAetP4egSif99AE9iD8EbiBzAt16OX7EN8
-d7xNiIN922Ep3pubcD6f1vglaI7Thrca/p52g6kWPip6+PWFd1acU6u31Uj0Xvgz
-VFiafstF+0cCgYEAw2sOcJFXCZ2Tnyjzav85jwZu95ek9CPUNJQGyXSsQAWUGdok
-+hf7q/mqDx9Maoqtpkv8z2bD7vZuCdvGjaee1U16wyS3GPhV69/ayjwxsi5slf5Y
-rIiZnPkUnMM5Jh2X2gMyFCSlp82ILdFwxIOn3tOR4gW411w0lfIilSYgevECgYA3
-JAgVZHREcdzH9seHrWLze+co+6/0cr26guO46YogRIp8s5tIF0tb5FCg8yijl+cR
-OMHzrs12h1aertCEfl9Ep4BVmUcd4uLpbqNtUfeY0FrtnIkRrCCKWYieF+mJC5No
-86/o0n1s752QCK51fxSwiJigVutJWkVP7uTCLr2cuwKBgQCJPWMcWmSuRlLOVWnO
-jPFoa02Bb83n8GrRpQkpkZZofHextwfo2dd1sZF72zghRsbdC6e0Zj1GrekJOYXO
-8AXmCpyKlXJU7iH5tPGSo68uFN05R6mINbTNmEIQBNTKv8UoKT+nHcTycFrVtarX
-A8EPW2xB86m+Bjq/GNyRgfbPMg==
------END PRIVATE KEY-----
-`)
-
-// An ECDSA key in the X.509 internal private key format.
-var ecdsaPrivate = []byte(`-----BEGIN EC PRIVATE KEY-----
-MGgCAQEEHF64kDx3pZyVvezbqYMIxlLbtuPQmI85k4GRy1mgBwYFK4EEACGhPAM6
-AASRtolOCTLQYkDefkIF02tUXR92MKHrbtH4WK/8bfTSFVkaygTPdJbpNthK2wae
-oX9ZeFHS1pcOfQ==
------END EC PRIVATE KEY-----
-`)
-
-// An ECDSA key in PKCS#8 format, no encryption.
-var ecdsaPkcs8Private = []byte(`-----BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHKeDq4UU6M+c+pMm
-j0AQZlBs7f4r67668eDCUB8aDR2hRANCAATyZPzsx+xn9JtlxdspevTrYisiMTjl
-YuBJCrV1FZj2HkplEgO+ZIMuD7eRvyTEBS2bw6F1aCeKOMUmYVImAbpc
------END PRIVATE KEY-----
-`)
-
-// A password-protected RSA private key in PKCS#5/8 format. The
-// password for this key is "sample".
-var rsaEncryptedPrivate = []byte(`-----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIRMifqJThk8kCAggA
-MB0GCWCGSAFlAwQBKgQQTMUBoFpzjJ5UNRnCIeqf4QSCBNDkQvXnUNmss8erKiDo
-Uqs2tf9ZD8MjDThLBmF/gV1dg1q6aDY+3fI2E4yLXJb2PmKcUq82YZ0FDeoCvJRJ
-BCurzM9slur5akpNBTFoFwtFsdHz7nKNS4MHUul22rGBnVFUUNTySmpjl/m+dxWO
-fa6tWpGTAr7tsCy9gF5PxpSw7NR/NpIL0PmpydHWhTs1tl2csqBqK6Tp014Kefi/
-pmmeb2eRl5cmprxW32rW2QBMtv4z91SsbnlVdz4r8txTG+3S4td9v9jD5kqcIiC2
-KQHrbH9y7okUk/ISsp9ANKPJt10fbYDxORiMK57XssXy1enGjpkIIrUGz1TMydkD
-USfwqkmPuIrrzOXnbxU4ef2wC/pA/h9Smby3WWYo8725/1kZyIediNDcgi/Qgrs4
-1VQAYzsD6duwyUNSo+tgmYVFGvZhsottus3fMWe/Ay1biJ6z6Vk8gqKWI1VV/REJ
-zK/I9hgKGxj2N2Ff6E/YkcwQenHWj/iDWLjvokyOBnPFNqzzM2Qqo1XFpzj4EO5D
-0WD4EzZYvUhk3lZZNydvXiuy8RrCVLLJMS08XgOqQaiFqqxj2hjRwv3nBesk7iA8
-5Tv8GMa5QkNrISCnp4/uGBh+v/CjwVRqPTcK3/mctPN2nLhI6H4pF4Y6apXkz1TN
-NMQqxaxmVVg8fyLaS4/xfUr8LAmiEtOwvs0XOhcqCTvvlsO4N+yec4VD4gmsTDY9
-/2b/+YwSlGMpA+GQQbg0FraaF8NyJRG1mSER6WiUGGM1cuKK44nzBbykQbZwzDSA
-kkhjDaadkhv/NPKAUR3sNy2GXVaNL/ItCpQUHRKKcIPp0HhdXsl0YebuwRlHjw/6
-UOdzNYe23e40X/Xl3vmOKRbzhLP/qO2DV21o0wI4ujF8Xu5h1h8s49HPp58G1ldy
-/hJ6durYKX8T5khiR2iXYewoy0YObuccV//Ov1/ySOp/x0/QuCl/swvs8Jf7awnu
-rpRrHPArpCvMmXmt5Y+TFYXFjkJGwsxTew5TcwBebBlIET2XNbo2pbz4WqJ3eVlK
-CNZVDEZ8mMrGT00FBi759Vfw9rhrnqXnLlNtJZ5VCXFUw8Tos302sLaQWXzHYyf8
-4awM8G9PSu5Q9lFcN9od4H95YrAAv/l8F+pcGgEKD8ZuzsgFIalqgx5wzmUMDcPM
-NKV5u9mtHjI92ru6NB8rGesM6sy6kBGvpotsDWawpV2SoCrkbyEkk+kXaGS+fsG7
-D2H37GfktN8R5Ktc0Uf/JJiNfDzq8lk1J4r7LBQlWUbhKbfGMYxt+7Xo0GsqAsLp
-PKSUwx+hTZb3BmW6s4Q6vivI1MdQbWVT1zh41StvfRSNlo70iOFxOM0lU1jjY989
-UKo+gcolddvZbMNwip0ILPO3dsa+he1jJ/gbo9qBHLy7plfsBLLakZP1Nu6xdlqQ
-TSSobaE8uxUMZk+wMWClA9AOZ1TcUr2yRV5GVj/bxG9ab+H37vF9F8vFE+jjJ7yN
-6pjdohm4gXeSVx7ON4SeZLsVwNYkCVYS89E81qLx1jP9F57+6IUGDZN5EMC0aJLT
-ny75MCCLT00KD7BFsb0KDLXxp++eu/L2hinorT3p6dXp/9mUoxmy6wJqEyqCFniZ
-N2GZN7+LDTIbHUxCijVWamU2DQ==
------END ENCRYPTED PRIVATE KEY-----
-`)
-
-// A password-protected ECDSA private key in PKCS#5/8 format. The
-// password for this key is "sample"
-var ecdsaEncryptedPrivate = []byte(`-----BEGIN ENCRYPTED PRIVATE KEY-----
-MIHeMEkGCSqGSIb3DQEFDTA8MBsGCSqGSIb3DQEFDDAOBAjlKrDSKNg9QQICCAAw
-HQYJYIZIAWUDBAEqBBDliPNzQTNpdlppTcYpmuhWBIGQVhfWaVSzUvi/qIZLiZVn
-Nulfw5jDOlbn3UBX9kp/Z9Pro582Q0kjzLfm5UahvDINEJWxL4pc/28UnGQTBr0Q
-nSEg+RbqpuD099C38H0Gq/YkIM+RDG4aiQrkmzHXyVsHshIbG+z2LsLTIwmU69/Z
-v0nX6/hGErVR8YWcrOne086rCvfJVrxyO5+EUqrkLhEr
------END ENCRYPTED PRIVATE KEY-----
-`)