github.com/rigado/snapd@v2.42.5-go-mod+incompatible/asserts/crypto.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2015-2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package asserts
    21  
    22  import (
    23  	"bytes"
    24  	"crypto"
    25  	"crypto/rand"
    26  	"crypto/rsa"
    27  	_ "crypto/sha256" // be explicit about supporting SHA256
    28  	_ "crypto/sha512" // be explicit about needing SHA512
    29  	"encoding/base64"
    30  	"fmt"
    31  	"io"
    32  	"time"
    33  
    34  	"golang.org/x/crypto/openpgp/packet"
    35  	"golang.org/x/crypto/sha3"
    36  )
    37  
    38  const (
    39  	maxEncodeLineLength = 76
    40  	v1                  = 0x1
    41  )
    42  
    43  var (
    44  	v1Header         = []byte{v1}
    45  	v1FixedTimestamp = time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC)
    46  )
    47  
    48  func encodeV1(data []byte) []byte {
    49  	buf := new(bytes.Buffer)
    50  	buf.Grow(base64.StdEncoding.EncodedLen(len(data) + 1))
    51  	enc := base64.NewEncoder(base64.StdEncoding, buf)
    52  	enc.Write(v1Header)
    53  	enc.Write(data)
    54  	enc.Close()
    55  	flat := buf.Bytes()
    56  	flatSize := len(flat)
    57  
    58  	buf = new(bytes.Buffer)
    59  	buf.Grow(flatSize + flatSize/maxEncodeLineLength + 1)
    60  	off := 0
    61  	for {
    62  		endOff := off + maxEncodeLineLength
    63  		if endOff > flatSize {
    64  			endOff = flatSize
    65  		}
    66  		buf.Write(flat[off:endOff])
    67  		off = endOff
    68  		if off >= flatSize {
    69  			break
    70  		}
    71  		buf.WriteByte('\n')
    72  	}
    73  
    74  	return buf.Bytes()
    75  }
    76  
    77  type keyEncoder interface {
    78  	keyEncode(w io.Writer) error
    79  }
    80  
    81  func encodeKey(key keyEncoder, kind string) ([]byte, error) {
    82  	buf := new(bytes.Buffer)
    83  	err := key.keyEncode(buf)
    84  	if err != nil {
    85  		return nil, fmt.Errorf("cannot encode %s: %v", kind, err)
    86  	}
    87  	return encodeV1(buf.Bytes()), nil
    88  }
    89  
    90  type openpgpSigner interface {
    91  	sign(content []byte) (*packet.Signature, error)
    92  }
    93  
    94  func signContent(content []byte, privateKey PrivateKey) ([]byte, error) {
    95  	signer, ok := privateKey.(openpgpSigner)
    96  	if !ok {
    97  		panic(fmt.Errorf("not an internally supported PrivateKey: %T", privateKey))
    98  	}
    99  
   100  	sig, err := signer.sign(content)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	buf := new(bytes.Buffer)
   106  	err = sig.Serialize(buf)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	return encodeV1(buf.Bytes()), nil
   112  }
   113  
   114  func decodeV1(b []byte, kind string) (packet.Packet, error) {
   115  	if len(b) == 0 {
   116  		return nil, fmt.Errorf("cannot decode %s: no data", kind)
   117  	}
   118  	buf := make([]byte, base64.StdEncoding.DecodedLen(len(b)))
   119  	n, err := base64.StdEncoding.Decode(buf, b)
   120  	if err != nil {
   121  		return nil, fmt.Errorf("cannot decode %s: %v", kind, err)
   122  	}
   123  	if n == 0 {
   124  		return nil, fmt.Errorf("cannot decode %s: base64 without data", kind)
   125  	}
   126  	buf = buf[:n]
   127  	if buf[0] != v1 {
   128  		return nil, fmt.Errorf("unsupported %s format version: %d", kind, buf[0])
   129  	}
   130  	rd := bytes.NewReader(buf[1:])
   131  	pkt, err := packet.Read(rd)
   132  	if err != nil {
   133  		return nil, fmt.Errorf("cannot decode %s: %v", kind, err)
   134  	}
   135  	if rd.Len() != 0 {
   136  		return nil, fmt.Errorf("%s has spurious trailing data", kind)
   137  	}
   138  	return pkt, nil
   139  }
   140  
   141  func decodeSignature(signature []byte) (*packet.Signature, error) {
   142  	pkt, err := decodeV1(signature, "signature")
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	sig, ok := pkt.(*packet.Signature)
   147  	if !ok {
   148  		return nil, fmt.Errorf("expected signature, got instead: %T", pkt)
   149  	}
   150  	return sig, nil
   151  }
   152  
   153  // PublicKey is the public part of a cryptographic private/public key pair.
   154  type PublicKey interface {
   155  	// ID returns the id of the key used for lookup.
   156  	ID() string
   157  
   158  	// verify verifies signature is valid for content using the key.
   159  	verify(content []byte, sig *packet.Signature) error
   160  
   161  	keyEncoder
   162  }
   163  
   164  type openpgpPubKey struct {
   165  	pubKey   *packet.PublicKey
   166  	sha3_384 string
   167  }
   168  
   169  func (opgPubKey *openpgpPubKey) ID() string {
   170  	return opgPubKey.sha3_384
   171  }
   172  
   173  func (opgPubKey *openpgpPubKey) verify(content []byte, sig *packet.Signature) error {
   174  	h := sig.Hash.New()
   175  	h.Write(content)
   176  	return opgPubKey.pubKey.VerifySignature(h, sig)
   177  }
   178  
   179  func (opgPubKey openpgpPubKey) keyEncode(w io.Writer) error {
   180  	return opgPubKey.pubKey.Serialize(w)
   181  }
   182  
   183  func newOpenPGPPubKey(intPubKey *packet.PublicKey) *openpgpPubKey {
   184  	h := sha3.New384()
   185  	h.Write(v1Header)
   186  	err := intPubKey.Serialize(h)
   187  	if err != nil {
   188  		panic("internal error: cannot compute public key sha3-384")
   189  	}
   190  	sha3_384, err := EncodeDigest(crypto.SHA3_384, h.Sum(nil))
   191  	if err != nil {
   192  		panic("internal error: cannot compute public key sha3-384")
   193  	}
   194  	return &openpgpPubKey{pubKey: intPubKey, sha3_384: sha3_384}
   195  }
   196  
   197  // RSAPublicKey returns a database useable public key out of rsa.PublicKey.
   198  func RSAPublicKey(pubKey *rsa.PublicKey) PublicKey {
   199  	intPubKey := packet.NewRSAPublicKey(v1FixedTimestamp, pubKey)
   200  	return newOpenPGPPubKey(intPubKey)
   201  }
   202  
   203  // DecodePublicKey deserializes a public key.
   204  func DecodePublicKey(pubKey []byte) (PublicKey, error) {
   205  	pkt, err := decodeV1(pubKey, "public key")
   206  	if err != nil {
   207  		return nil, err
   208  	}
   209  	pubk, ok := pkt.(*packet.PublicKey)
   210  	if !ok {
   211  		return nil, fmt.Errorf("expected public key, got instead: %T", pkt)
   212  	}
   213  	rsaPubKey, ok := pubk.PublicKey.(*rsa.PublicKey)
   214  	if !ok {
   215  		return nil, fmt.Errorf("expected RSA public key, got instead: %T", pubk.PublicKey)
   216  	}
   217  	return RSAPublicKey(rsaPubKey), nil
   218  }
   219  
   220  // EncodePublicKey serializes a public key, typically for embedding in an assertion.
   221  func EncodePublicKey(pubKey PublicKey) ([]byte, error) {
   222  	return encodeKey(pubKey, "public key")
   223  }
   224  
   225  // PrivateKey is a cryptographic private/public key pair.
   226  type PrivateKey interface {
   227  	// PublicKey returns the public part of the pair.
   228  	PublicKey() PublicKey
   229  
   230  	keyEncoder
   231  }
   232  
   233  type openpgpPrivateKey struct {
   234  	privk *packet.PrivateKey
   235  }
   236  
   237  func (opgPrivK openpgpPrivateKey) PublicKey() PublicKey {
   238  	return newOpenPGPPubKey(&opgPrivK.privk.PublicKey)
   239  }
   240  
   241  func (opgPrivK openpgpPrivateKey) keyEncode(w io.Writer) error {
   242  	return opgPrivK.privk.Serialize(w)
   243  }
   244  
   245  var openpgpConfig = &packet.Config{
   246  	DefaultHash: crypto.SHA512,
   247  }
   248  
   249  func (opgPrivK openpgpPrivateKey) sign(content []byte) (*packet.Signature, error) {
   250  	privk := opgPrivK.privk
   251  	sig := new(packet.Signature)
   252  	sig.PubKeyAlgo = privk.PubKeyAlgo
   253  	sig.Hash = openpgpConfig.Hash()
   254  	sig.CreationTime = time.Now()
   255  
   256  	h := openpgpConfig.Hash().New()
   257  	h.Write(content)
   258  
   259  	err := sig.Sign(h, privk, openpgpConfig)
   260  	if err != nil {
   261  		return nil, err
   262  	}
   263  
   264  	return sig, nil
   265  }
   266  
   267  func decodePrivateKey(privKey []byte) (PrivateKey, error) {
   268  	pkt, err := decodeV1(privKey, "private key")
   269  	if err != nil {
   270  		return nil, err
   271  	}
   272  	privk, ok := pkt.(*packet.PrivateKey)
   273  	if !ok {
   274  		return nil, fmt.Errorf("expected private key, got instead: %T", pkt)
   275  	}
   276  	if _, ok := privk.PrivateKey.(*rsa.PrivateKey); !ok {
   277  		return nil, fmt.Errorf("expected RSA private key, got instead: %T", privk.PrivateKey)
   278  	}
   279  	return openpgpPrivateKey{privk}, nil
   280  }
   281  
   282  // RSAPrivateKey returns a PrivateKey for database use out of a rsa.PrivateKey.
   283  func RSAPrivateKey(privk *rsa.PrivateKey) PrivateKey {
   284  	intPrivk := packet.NewRSAPrivateKey(v1FixedTimestamp, privk)
   285  	return openpgpPrivateKey{intPrivk}
   286  }
   287  
   288  // GenerateKey generates a private/public key pair.
   289  func GenerateKey() (PrivateKey, error) {
   290  	priv, err := rsa.GenerateKey(rand.Reader, 4096)
   291  	if err != nil {
   292  		return nil, err
   293  	}
   294  	return RSAPrivateKey(priv), nil
   295  }
   296  
   297  func encodePrivateKey(privKey PrivateKey) ([]byte, error) {
   298  	return encodeKey(privKey, "private key")
   299  }
   300  
   301  // externally held key pairs
   302  
   303  type extPGPPrivateKey struct {
   304  	pubKey         PublicKey
   305  	from           string
   306  	pgpFingerprint string
   307  	bitLen         int
   308  	doSign         func(content []byte) ([]byte, error)
   309  }
   310  
   311  func newExtPGPPrivateKey(exportedPubKeyStream io.Reader, from string, sign func(content []byte) ([]byte, error)) (*extPGPPrivateKey, error) {
   312  	var pubKey *packet.PublicKey
   313  
   314  	rd := packet.NewReader(exportedPubKeyStream)
   315  	for {
   316  		pkt, err := rd.Next()
   317  		if err == io.EOF {
   318  			break
   319  		}
   320  		if err != nil {
   321  			return nil, fmt.Errorf("cannot read exported public key: %v", err)
   322  		}
   323  		cand, ok := pkt.(*packet.PublicKey)
   324  		if ok {
   325  			if cand.IsSubkey {
   326  				continue
   327  			}
   328  			if pubKey != nil {
   329  				return nil, fmt.Errorf("cannot select exported public key, found many")
   330  			}
   331  			pubKey = cand
   332  		}
   333  	}
   334  
   335  	if pubKey == nil {
   336  		return nil, fmt.Errorf("cannot read exported public key, found none (broken export)")
   337  
   338  	}
   339  
   340  	rsaPubKey, ok := pubKey.PublicKey.(*rsa.PublicKey)
   341  	if !ok {
   342  		return nil, fmt.Errorf("not a RSA key")
   343  	}
   344  
   345  	return &extPGPPrivateKey{
   346  		pubKey:         RSAPublicKey(rsaPubKey),
   347  		from:           from,
   348  		pgpFingerprint: fmt.Sprintf("%X", pubKey.Fingerprint),
   349  		bitLen:         rsaPubKey.N.BitLen(),
   350  		doSign:         sign,
   351  	}, nil
   352  }
   353  
   354  func (expk *extPGPPrivateKey) fingerprint() string {
   355  	return expk.pgpFingerprint
   356  }
   357  
   358  func (expk *extPGPPrivateKey) PublicKey() PublicKey {
   359  	return expk.pubKey
   360  }
   361  
   362  func (expk *extPGPPrivateKey) keyEncode(w io.Writer) error {
   363  	return fmt.Errorf("cannot access external private key to encode it")
   364  }
   365  
   366  func (expk *extPGPPrivateKey) sign(content []byte) (*packet.Signature, error) {
   367  	if expk.bitLen < 4096 {
   368  		return nil, fmt.Errorf("signing needs at least a 4096 bits key, got %d", expk.bitLen)
   369  	}
   370  
   371  	out, err := expk.doSign(content)
   372  	if err != nil {
   373  		return nil, err
   374  	}
   375  
   376  	badSig := fmt.Sprintf("bad %s produced signature: ", expk.from)
   377  
   378  	sigpkt, err := packet.Read(bytes.NewBuffer(out))
   379  	if err != nil {
   380  		return nil, fmt.Errorf(badSig+"%v", err)
   381  	}
   382  
   383  	sig, ok := sigpkt.(*packet.Signature)
   384  	if !ok {
   385  		return nil, fmt.Errorf(badSig+"got %T", sigpkt)
   386  	}
   387  
   388  	if sig.Hash != crypto.SHA512 {
   389  		return nil, fmt.Errorf(badSig + "expected SHA512 digest")
   390  	}
   391  
   392  	err = expk.pubKey.verify(content, sig)
   393  	if err != nil {
   394  		return nil, fmt.Errorf(badSig+"it does not verify: %v", err)
   395  	}
   396  
   397  	return sig, nil
   398  }