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-artifact.git

commit 1447da7b29f30f7909aa739ae455744d1d850a42
Author: Christopher Collins <ccoll...@apache.org>
AuthorDate: Thu Jan 10 13:08:51 2019 -0800

    Create new package: artifact/sec
    
    This package contains generic security functionality.
    
    Since mfgimages now require signatures (not just normal images), it
    doesn't make sense to keep all the security functionality in the `image`
    package.
---
 image/create.go                   | 111 ++++++++++++++++++++++----------------
 image/keys_test.go                |  63 +++++++---------------
 image/v1.go                       |  27 +++++-----
 sec/encrypt.go                    |  42 +++++++++++++++
 {image => sec}/key.go             |  98 ++++++++++-----------------------
 image/encrypted.go => sec/pkcs.go |   3 +-
 6 files changed, 167 insertions(+), 177 deletions(-)

diff --git a/image/create.go b/image/create.go
index 76e701d..3ec8770 100644
--- a/image/create.go
+++ b/image/create.go
@@ -22,8 +22,6 @@ package image
 import (
        "bytes"
        "crypto"
-       "crypto/aes"
-       "crypto/cipher"
        "crypto/ecdsa"
        "crypto/rand"
        "crypto/rsa"
@@ -31,17 +29,17 @@ import (
        "encoding/asn1"
        "encoding/binary"
        "encoding/hex"
-       "io"
        "io/ioutil"
        "math/big"
 
+       "mynewt.apache.org/newt/artifact/sec"
        "mynewt.apache.org/newt/util"
 )
 
 type ImageCreator struct {
        Body         []byte
        Version      ImageVersion
-       SigKeys      []ImageSigKey
+       SigKeys      []sec.SignKey
        PlainSecret  []byte
        CipherSecret []byte
        HeaderSize   int
@@ -53,7 +51,7 @@ type ImageCreateOpts struct {
        SrcBinFilename    string
        SrcEncKeyFilename string
        Version           ImageVersion
-       SigKeys           []ImageSigKey
+       SigKeys           []sec.SignKey
        LoaderHash        []byte
 }
 
@@ -69,6 +67,23 @@ func NewImageCreator() ImageCreator {
        }
 }
 
+func sigTlvType(key sec.SignKey) uint8 {
+       key.AssertValid()
+
+       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 GenerateEncTlv(cipherSecret []byte) (ImageTlv, error) {
        var encType uint8
 
@@ -90,7 +105,7 @@ func GenerateEncTlv(cipherSecret []byte) (ImageTlv, error) {
        }, nil
 }
 
-func GenerateSigRsa(key ImageSigKey, hash []byte) ([]byte, error) {
+func GenerateSigRsa(key sec.SignKey, hash []byte) ([]byte, error) {
        opts := rsa.PSSOptions{
                SaltLength: rsa.PSSSaltLengthEqualsHash,
        }
@@ -103,7 +118,7 @@ func GenerateSigRsa(key ImageSigKey, hash []byte) ([]byte, 
error) {
        return signature, nil
 }
 
-func GenerateSigEc(key ImageSigKey, hash []byte) ([]byte, error) {
+func GenerateSigEc(key sec.SignKey, hash []byte) ([]byte, error) {
        r, s, err := ecdsa.Sign(rand.Reader, key.Ec, hash)
        if err != nil {
                return nil, util.FmtNewtError("Failed to compute signature: 
%s", err)
@@ -119,7 +134,7 @@ func GenerateSigEc(key ImageSigKey, hash []byte) ([]byte, 
error) {
                return nil, util.FmtNewtError("Failed to construct signature: 
%s", err)
        }
 
-       sigLen := key.sigLen()
+       sigLen := key.SigLen()
        if len(signature) > int(sigLen) {
                return nil, util.FmtNewtError("Something is really wrong\n")
        }
@@ -130,8 +145,8 @@ func GenerateSigEc(key ImageSigKey, hash []byte) ([]byte, 
error) {
        return signature, nil
 }
 
-func GenerateSig(key ImageSigKey, hash []byte) ([]byte, error) {
-       key.assertValid()
+func GenerateSig(key sec.SignKey, hash []byte) ([]byte, error) {
+       key.AssertValid()
 
        if key.Rsa != nil {
                return GenerateSigRsa(key, hash)
@@ -141,7 +156,7 @@ func GenerateSig(key ImageSigKey, hash []byte) ([]byte, 
error) {
 }
 
 func BuildKeyHashTlv(keyBytes []byte) ImageTlv {
-       data := RawKeyHash(keyBytes)
+       data := sec.RawKeyHash(keyBytes)
        return ImageTlv{
                Header: ImageTlvHdr{
                        Type: IMAGE_TLV_KEYHASH,
@@ -152,11 +167,11 @@ func BuildKeyHashTlv(keyBytes []byte) ImageTlv {
        }
 }
 
-func BuildSigTlvs(keys []ImageSigKey, hash []byte) ([]ImageTlv, error) {
+func BuildSigTlvs(keys []sec.SignKey, hash []byte) ([]ImageTlv, error) {
        var tlvs []ImageTlv
 
        for _, key := range keys {
-               key.assertValid()
+               key.AssertValid()
 
                // Key hash TLV.
                pubKey, err := key.PubBytes()
@@ -173,7 +188,7 @@ func BuildSigTlvs(keys []ImageSigKey, hash []byte) 
([]ImageTlv, error) {
                }
                tlv = ImageTlv{
                        Header: ImageTlvHdr{
-                               Type: key.sigTlvType(),
+                               Type: sigTlvType(key),
                                Len:  uint16(len(sig)),
                        },
                        Data: sig,
@@ -184,6 +199,40 @@ func BuildSigTlvs(keys []ImageSigKey, hash []byte) 
([]ImageTlv, error) {
        return tlvs, nil
 }
 
+func GeneratePlainSecret() ([]byte, error) {
+       plainSecret := make([]byte, 16)
+       if _, err := rand.Read(plainSecret); err != nil {
+               return nil, util.FmtNewtError(
+                       "Random generation error: %s\n", err)
+       }
+
+       return plainSecret, nil
+}
+
+func GenerateCipherSecret(pubKeBytes []byte,
+       plainSecret []byte) ([]byte, error) {
+
+       // Try reading as PEM (asymetric key).
+       rsaPubKe, err := sec.ParsePubKePem(pubKeBytes)
+       if err != nil {
+               return nil, err
+       }
+       if rsaPubKe != nil {
+               return sec.EncryptSecretRsa(rsaPubKe, plainSecret)
+       }
+
+       // Not PEM; assume this is a base64 encoded symetric key
+       aesPubKe, err := sec.ParseKeBase64(pubKeBytes)
+       if err != nil {
+               return nil, err
+       }
+       if aesPubKe != nil {
+               return sec.EncryptSecretAes(aesPubKe, plainSecret)
+       }
+
+       return nil, util.FmtNewtError("Invalid image-crypt key")
+}
+
 func GenerateImage(opts ImageCreateOpts) (Image, error) {
        ic := NewImageCreator()
 
@@ -279,38 +328,6 @@ func calcHash(initialHash []byte, hdr ImageHdr, pad []byte,
        return hash.Sum(nil), nil
 }
 
-func EncryptImageBody(imageBody []byte, secret []byte) ([]byte, error) {
-       block, err := aes.NewCipher(secret)
-       if err != nil {
-               return nil, util.NewNewtError("Failed to create block cipher")
-       }
-       nonce := make([]byte, 16)
-       stream := cipher.NewCTR(block, nonce)
-
-       dataBuf := make([]byte, 16)
-       encBuf := make([]byte, 16)
-       r := bytes.NewReader(imageBody)
-       w := bytes.Buffer{}
-       for {
-               cnt, err := r.Read(dataBuf)
-               if err != nil && err != io.EOF {
-                       return nil, util.FmtNewtError(
-                               "Failed to read from image body: %s", 
err.Error())
-               }
-               if cnt == 0 {
-                       break
-               }
-
-               stream.XORKeyStream(encBuf, dataBuf[0:cnt])
-               if _, err = w.Write(encBuf[0:cnt]); err != nil {
-                       return nil, util.FmtNewtError(
-                               "Failed to write to image body: %s", 
err.Error())
-               }
-       }
-
-       return w.Bytes(), nil
-}
-
 func (ic *ImageCreator) Create() (Image, error) {
        img := Image{}
 
@@ -354,7 +371,7 @@ func (ic *ImageCreator) Create() (Image, error) {
 
        // Followed by data.
        if ic.CipherSecret != nil {
-               encBody, err := EncryptImageBody(ic.Body, ic.PlainSecret)
+               encBody, err := sec.EncryptAES(ic.Body, ic.PlainSecret)
                if err != nil {
                        return img, err
                }
diff --git a/image/keys_test.go b/image/keys_test.go
index 577d9cd..769848a 100644
--- a/image/keys_test.go
+++ b/image/keys_test.go
@@ -22,8 +22,10 @@ package image_test
 import (
        "io/ioutil"
        "os"
-       "path"
        "testing"
+
+       "mynewt.apache.org/newt/artifact/image"
+       "mynewt.apache.org/newt/artifact/sec"
 )
 
 func TestRSA(t *testing.T) {
@@ -43,15 +45,15 @@ func TestPlainEcdsaPkcs8(t *testing.T) {
 }
 
 func TestEncryptedRSA(t *testing.T) {
-       image.KeyPassword = []byte("sample")
+       sec.KeyPassword = []byte("sample")
        signatureTest(t, rsaEncryptedPrivate)
-       image.KeyPassword = []byte{}
+       sec.KeyPassword = []byte{}
 }
 
 func TestEncryptedEcdsa(t *testing.T) {
-       image.KeyPassword = []byte("sample")
+       sec.KeyPassword = []byte("sample")
        signatureTest(t, ecdsaEncryptedPrivate)
-       image.KeyPassword = []byte{}
+       sec.KeyPassword = []byte{}
 }
 
 func signatureTest(t *testing.T, privateKey []byte) {
@@ -65,58 +67,29 @@ func signatureTest(t *testing.T, privateKey []byte) {
        // 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)
+       body := make([]byte, 256)
+       for i := 0; i < len(body); i++ {
+               body[i] = byte(i)
        }
 
-       img, err := image.NewImage(simpleName, hashedName)
-       if err != nil {
-               t.Fatal(err)
-       }
-
-       img.SetVersion("1.5")
-       if err != nil {
-               t.Fatal(err)
-       }
+       ic := image.NewImageCreator()
+       ic.Version = image.ImageVersion{1, 5, 0, 0}
+       ic.Body = body
 
-       img.Generate(nil)
-       if err != nil {
+       if _, err := ic.Create(); err != nil {
                t.Fatal(err)
        }
 
        // Now try with a signature.
-       err = ioutil.WriteFile(keyName, privateKey, 0644)
+       key, err := sec.BuildPrivateKey(privateKey)
        if err != nil {
                t.Fatal(err)
        }
+       ic.SigKeys = append(ic.SigKeys, key)
 
-       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)
-       }
+       ic.Version = image.ImageVersion{1, 6, 0, 0}
 
-       err = img.Generate(nil)
-       if err != nil {
+       if _, err := ic.Create(); err != nil {
                t.Fatal(err)
        }
 }
diff --git a/image/v1.go b/image/v1.go
index 0dc10a5..67a451f 100644
--- a/image/v1.go
+++ b/image/v1.go
@@ -34,6 +34,7 @@ import (
        "io"
        "io/ioutil"
 
+       "mynewt.apache.org/newt/artifact/sec"
        "mynewt.apache.org/newt/util"
 )
 
@@ -157,8 +158,8 @@ func (img *ImageV1) Write(w io.Writer) (int, error) {
        return offs.TotalSize, nil
 }
 
-func (key *ImageSigKey) sigHdrTypeV1() (uint32, error) {
-       key.assertValid()
+func sigHdrTypeV1(key sec.SignKey) (uint32, error) {
+       key.AssertValid()
 
        if key.Rsa != nil {
                if UseRsaPss {
@@ -178,8 +179,8 @@ func (key *ImageSigKey) sigHdrTypeV1() (uint32, error) {
        }
 }
 
-func (key *ImageSigKey) sigTlvTypeV1() uint8 {
-       key.assertValid()
+func sigTlvTypeV1(key sec.SignKey) uint8 {
+       key.AssertValid()
 
        if key.Rsa != nil {
                return IMAGEv1_TLV_RSA2048
@@ -216,7 +217,7 @@ func generateV1SigRsa(key *rsa.PrivateKey, hash []byte) 
([]byte, error) {
        return signature, nil
 }
 
-func generateV1SigTlvRsa(key ImageSigKey, hash []byte) (ImageTlv, error) {
+func generateV1SigTlvRsa(key sec.SignKey, hash []byte) (ImageTlv, error) {
        sig, err := generateV1SigRsa(key.Rsa, hash)
        if err != nil {
                return ImageTlv{}, err
@@ -224,7 +225,7 @@ func generateV1SigTlvRsa(key ImageSigKey, hash []byte) 
(ImageTlv, error) {
 
        return ImageTlv{
                Header: ImageTlvHdr{
-                       Type: key.sigTlvTypeV1(),
+                       Type: sigTlvTypeV1(key),
                        Pad:  0,
                        Len:  256, /* 2048 bits */
                },
@@ -232,13 +233,13 @@ func generateV1SigTlvRsa(key ImageSigKey, hash []byte) 
(ImageTlv, error) {
        }, nil
 }
 
-func generateV1SigTlvEc(key ImageSigKey, hash []byte) (ImageTlv, error) {
+func generateV1SigTlvEc(key sec.SignKey, hash []byte) (ImageTlv, error) {
        sig, err := GenerateSigEc(key, hash)
        if err != nil {
                return ImageTlv{}, err
        }
 
-       sigLen := key.sigLen()
+       sigLen := key.SigLen()
        if len(sig) > int(sigLen) {
                return ImageTlv{}, util.FmtNewtError("Something is really 
wrong\n")
        }
@@ -258,7 +259,7 @@ func generateV1SigTlvEc(key ImageSigKey, hash []byte) 
(ImageTlv, error) {
 
        return ImageTlv{
                Header: ImageTlvHdr{
-                       Type: key.sigTlvTypeV1(),
+                       Type: sigTlvTypeV1(key),
                        Pad:  0,
                        Len:  sigLen + uint16(len(pad)),
                },
@@ -266,8 +267,8 @@ func generateV1SigTlvEc(key ImageSigKey, hash []byte) 
(ImageTlv, error) {
        }, nil
 }
 
-func generateV1SigTlv(key ImageSigKey, hash []byte) (ImageTlv, error) {
-       key.assertValid()
+func generateV1SigTlv(key sec.SignKey, hash []byte) (ImageTlv, error) {
+       key.AssertValid()
 
        if key.Rsa != nil {
                return generateV1SigTlvRsa(key, hash)
@@ -356,12 +357,12 @@ func (ic *ImageCreator) CreateV1() (ImageV1, error) {
        }
 
        if len(ic.SigKeys) > 0 {
-               keyFlag, err := ic.SigKeys[0].sigHdrTypeV1()
+               keyFlag, err := sigHdrTypeV1(ic.SigKeys[0])
                if err != nil {
                        return ri, err
                }
                hdr.Flags |= keyFlag
-               hdr.TlvSz = 4 + ic.SigKeys[0].sigLen()
+               hdr.TlvSz = 4 + ic.SigKeys[0].SigLen()
        }
        hdr.TlvSz += 4 + 32
 
diff --git a/sec/encrypt.go b/sec/encrypt.go
new file mode 100644
index 0000000..bd99594
--- /dev/null
+++ b/sec/encrypt.go
@@ -0,0 +1,42 @@
+package sec
+
+import (
+       "bytes"
+       "crypto/aes"
+       "crypto/cipher"
+       "io"
+
+       "mynewt.apache.org/newt/util"
+)
+
+func EncryptAES(plain []byte, secret []byte) ([]byte, error) {
+       block, err := aes.NewCipher(secret)
+       if err != nil {
+               return nil, util.NewNewtError("Failed to create block cipher")
+       }
+       nonce := make([]byte, 16)
+       stream := cipher.NewCTR(block, nonce)
+
+       dataBuf := make([]byte, 16)
+       encBuf := make([]byte, 16)
+       r := bytes.NewReader(plain)
+       w := bytes.Buffer{}
+       for {
+               cnt, err := r.Read(dataBuf)
+               if err != nil && err != io.EOF {
+                       return nil, util.FmtNewtError(
+                               "Failed to read from plaintext: %s", 
err.Error())
+               }
+               if cnt == 0 {
+                       break
+               }
+
+               stream.XORKeyStream(encBuf, dataBuf[0:cnt])
+               if _, err = w.Write(encBuf[0:cnt]); err != nil {
+                       return nil, util.FmtNewtError(
+                               "Failed to write ciphertext: %s", err.Error())
+               }
+       }
+
+       return w.Bytes(), nil
+}
diff --git a/image/key.go b/sec/key.go
similarity index 77%
rename from image/key.go
rename to sec/key.go
index a343e2d..89b5f49 100644
--- a/image/key.go
+++ b/sec/key.go
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package image
+package sec
 
 import (
        "crypto/aes"
@@ -37,7 +37,7 @@ import (
        "mynewt.apache.org/newt/util"
 )
 
-type ImageSigKey struct {
+type SignKey struct {
        // Only one of these members is non-nil.
        Rsa *rsa.PrivateKey
        Ec  *ecdsa.PrivateKey
@@ -92,24 +92,21 @@ func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
                // encryption.
                privKey, err = parseEncryptedPrivateKey(block.Bytes)
                if err != nil {
-                       return nil, util.FmtNewtError("Unable to decode 
encrypted private key: %s", err)
+                       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 nil, util.NewNewtError(
+                       "Unknown private key format, EC/RSA private " +
+                               "key in PEM format only.")
        }
 
        return privKey, nil
 }
 
-func ReadKey(filename string) (ImageSigKey, error) {
-       key := ImageSigKey{}
-
-       keyBytes, err := ioutil.ReadFile(filename)
-       if err != nil {
-               return key, util.FmtNewtError("Error reading key file: %s", err)
-       }
+func BuildPrivateKey(keyBytes []byte) (SignKey, error) {
+       key := SignKey{}
 
        privKey, err := ParsePrivateKey(keyBytes)
        if err != nil {
@@ -128,8 +125,18 @@ func ReadKey(filename string) (ImageSigKey, error) {
        return key, nil
 }
 
-func ReadKeys(filenames []string) ([]ImageSigKey, error) {
-       keys := make([]ImageSigKey, len(filenames))
+func ReadKey(filename string) (SignKey, error) {
+       keyBytes, err := ioutil.ReadFile(filename)
+       if err != nil {
+               return SignKey{}, util.FmtNewtError(
+                       "Error reading key file: %s", err)
+       }
+
+       return BuildPrivateKey(keyBytes)
+}
+
+func ReadKeys(filenames []string) ([]SignKey, error) {
+       keys := make([]SignKey, len(filenames))
 
        for i, filename := range filenames {
                key, err := ReadKey(filename)
@@ -143,7 +150,7 @@ func ReadKeys(filenames []string) ([]ImageSigKey, error) {
        return keys, nil
 }
 
-func (key *ImageSigKey) assertValid() {
+func (key *SignKey) AssertValid() {
        if key.Rsa == nil && key.Ec == nil {
                panic("invalid key; neither RSA nor ECC")
        }
@@ -153,8 +160,8 @@ func (key *ImageSigKey) assertValid() {
        }
 }
 
-func (key *ImageSigKey) PubBytes() ([]uint8, error) {
-       key.assertValid()
+func (key *SignKey) PubBytes() ([]uint8, error) {
+       key.AssertValid()
 
        var pubkey []byte
 
@@ -179,8 +186,8 @@ func RawKeyHash(pubKeyBytes []byte) []byte {
        return sum[:4]
 }
 
-func (key *ImageSigKey) sigLen() uint16 {
-       key.assertValid()
+func (key *SignKey) SigLen() uint16 {
+       key.AssertValid()
 
        if key.Rsa != nil {
                return 256
@@ -196,23 +203,6 @@ func (key *ImageSigKey) sigLen() uint16 {
        }
 }
 
-func (key *ImageSigKey) sigTlvType() uint8 {
-       key.assertValid()
-
-       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 ParsePubKePem(keyBytes []byte) (*rsa.PublicKey, error) {
        b, _ := pem.Decode(keyBytes)
        if b == nil {
@@ -297,7 +287,7 @@ func ParseKeBase64(keyBytes []byte) (cipher.Block, error) {
        return cipher, nil
 }
 
-func encryptSecretAes(c cipher.Block, plainSecret []byte) ([]byte, error) {
+func EncryptSecretAes(c cipher.Block, plainSecret []byte) ([]byte, error) {
        cipherSecret, err := keywrap.Wrap(c, plainSecret)
        if err != nil {
                return nil, util.FmtNewtError("Error key-wrapping: %s", 
err.Error())
@@ -305,37 +295,3 @@ func encryptSecretAes(c cipher.Block, plainSecret []byte) 
([]byte, error) {
 
        return cipherSecret, nil
 }
-
-func GeneratePlainSecret() ([]byte, error) {
-       plainSecret := make([]byte, 16)
-       if _, err := rand.Read(plainSecret); err != nil {
-               return nil, util.FmtNewtError(
-                       "Random generation error: %s\n", err)
-       }
-
-       return plainSecret, nil
-}
-
-func GenerateCipherSecret(pubKeBytes []byte,
-       plainSecret []byte) ([]byte, error) {
-
-       // Try reading as PEM (asymetric key).
-       rsaPubKe, err := ParsePubKePem(pubKeBytes)
-       if err != nil {
-               return nil, err
-       }
-       if rsaPubKe != nil {
-               return EncryptSecretRsa(rsaPubKe, plainSecret)
-       }
-
-       // Not PEM; assume this is a base64 encoded symetric key
-       aesPubKe, err := ParseKeBase64(pubKeBytes)
-       if err != nil {
-               return nil, err
-       }
-       if aesPubKe != nil {
-               return encryptSecretAes(aesPubKe, plainSecret)
-       }
-
-       return nil, util.FmtNewtError("Invalid image-crypt key")
-}
diff --git a/image/encrypted.go b/sec/pkcs.go
similarity index 99%
rename from image/encrypted.go
rename to sec/pkcs.go
index 0547e2f..3cf709f 100644
--- a/image/encrypted.go
+++ b/sec/pkcs.go
@@ -18,7 +18,7 @@
  */
 
 // Decoder for PKCS#5 encrypted PKCS#8 private keys.
-package image
+package sec
 
 import (
        "crypto/aes"
@@ -78,6 +78,7 @@ type hashFunc func() hash.Hash
 
 func parseEncryptedPrivateKey(der []byte) (key interface{}, err error) {
        var wrapper pkcs5
+       fmt.Printf("unmarshalling %v\n", der)
        if _, err = asn1.Unmarshal(der, &wrapper); err != nil {
                return nil, err
        }

Reply via email to