...

Source file src/github.com/sigstore/rekor/pkg/pki/tuf/tuf.go

Documentation: github.com/sigstore/rekor/pkg/pki/tuf

     1  //
     2  // Copyright 2021 The Sigstore Authors.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package tuf
    17  
    18  import (
    19  	"crypto/ed25519"
    20  	"crypto/sha256"
    21  	"crypto/x509"
    22  	"encoding/hex"
    23  	"encoding/json"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"time"
    28  
    29  	"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
    30  	"github.com/sigstore/rekor/pkg/pki/identity"
    31  	"github.com/sigstore/sigstore/pkg/cryptoutils"
    32  	sigsig "github.com/sigstore/sigstore/pkg/signature"
    33  	"github.com/theupdateframework/go-tuf/data"
    34  	"github.com/theupdateframework/go-tuf/pkg/keys"
    35  	"github.com/theupdateframework/go-tuf/verify"
    36  )
    37  
    38  type Signature struct {
    39  	signed  *data.Signed
    40  	Role    string
    41  	Version int
    42  }
    43  
    44  type signedMeta struct {
    45  	Type        string    `json:"_type"`
    46  	Expires     time.Time `json:"expires"`
    47  	Version     int       `json:"version"`
    48  	SpecVersion string    `json:"spec_version"`
    49  }
    50  
    51  // NewSignature creates and validates a TUF signed manifest
    52  func NewSignature(r io.Reader) (*Signature, error) {
    53  	b, err := io.ReadAll(r)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	s := &data.Signed{}
    59  	if err := json.Unmarshal(b, s); err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	// extract role
    64  	sm := &signedMeta{}
    65  	if err := json.Unmarshal(s.Signed, sm); err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	return &Signature{
    70  		signed:  s,
    71  		Role:    sm.Type,
    72  		Version: sm.Version,
    73  	}, nil
    74  }
    75  
    76  // CanonicalValue implements the pki.Signature interface
    77  func (s Signature) CanonicalValue() ([]byte, error) {
    78  	if s.signed == nil {
    79  		return nil, errors.New("tuf manifest has not been initialized")
    80  	}
    81  	marshalledBytes, err := json.Marshal(s.signed)
    82  	if err != nil {
    83  		return nil, fmt.Errorf("marshalling signature: %w", err)
    84  	}
    85  	return jsoncanonicalizer.Transform(marshalledBytes)
    86  }
    87  
    88  // Verify implements the pki.Signature interface
    89  func (s Signature) Verify(_ io.Reader, k interface{}, _ ...sigsig.VerifyOption) error {
    90  	key, ok := k.(*PublicKey)
    91  	if !ok {
    92  		return fmt.Errorf("invalid public key type for: %v", k)
    93  	}
    94  
    95  	if key.db == nil {
    96  		return errors.New("tuf root has not been initialized")
    97  	}
    98  
    99  	return key.db.Verify(s.signed, s.Role, 0)
   100  }
   101  
   102  // PublicKey Public Key database with verification keys
   103  type PublicKey struct {
   104  	// we keep the signed root to retrieve the canonical value
   105  	root *data.Signed
   106  	db   *verify.DB
   107  }
   108  
   109  // NewPublicKey implements the pki.PublicKey interface
   110  func NewPublicKey(r io.Reader) (*PublicKey, error) {
   111  	rawRoot, err := io.ReadAll(r)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	// Unmarshal this to verify that this is a valid root.json
   117  	s := &data.Signed{}
   118  	if err := json.Unmarshal(rawRoot, s); err != nil {
   119  		return nil, err
   120  	}
   121  	root := &data.Root{}
   122  	if err := json.Unmarshal(s.Signed, root); err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	// Now create a verification db that trusts all the keys
   127  	db := verify.NewDB()
   128  	for id, k := range root.Keys {
   129  		if err := db.AddKey(id, k); err != nil {
   130  			return nil, err
   131  		}
   132  	}
   133  	for name, role := range root.Roles {
   134  		if err := db.AddRole(name, role); err != nil {
   135  			return nil, err
   136  		}
   137  	}
   138  
   139  	// Verify that this root.json was signed.
   140  	if err := db.Verify(s, "root", 0); err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	return &PublicKey{root: s, db: db}, nil
   145  }
   146  
   147  // CanonicalValue implements the pki.PublicKey interface
   148  func (k PublicKey) CanonicalValue() (encoded []byte, err error) {
   149  	if k.root == nil {
   150  		return nil, errors.New("tuf root has not been initialized")
   151  	}
   152  	marshalledBytes, err := json.Marshal(k.root)
   153  	if err != nil {
   154  		return nil, fmt.Errorf("marshalling tuf root: %w", err)
   155  	}
   156  	return jsoncanonicalizer.Transform(marshalledBytes)
   157  }
   158  
   159  func (k PublicKey) SpecVersion() (string, error) {
   160  	// extract role
   161  	sm := &signedMeta{}
   162  	if err := json.Unmarshal(k.root.Signed, sm); err != nil {
   163  		return "", err
   164  	}
   165  	return sm.SpecVersion, nil
   166  }
   167  
   168  // EmailAddresses implements the pki.PublicKey interface
   169  func (k PublicKey) EmailAddresses() []string {
   170  	return nil
   171  }
   172  
   173  // Subjects implements the pki.PublicKey interface
   174  func (k PublicKey) Subjects() []string {
   175  	return nil
   176  }
   177  
   178  // Identities implements the pki.PublicKey interface
   179  func (k PublicKey) Identities() ([]identity.Identity, error) {
   180  	root := &data.Root{}
   181  	if err := json.Unmarshal(k.root.Signed, root); err != nil {
   182  		return nil, err
   183  	}
   184  	var ids []identity.Identity
   185  	for _, k := range root.Keys {
   186  		verifier, err := keys.GetVerifier(k)
   187  		if err != nil {
   188  			return nil, err
   189  		}
   190  		switch k.Type {
   191  		// RSA and ECDSA keys are PKIX-encoded without PEM header for the Verifier type
   192  		case data.KeyTypeRSASSA_PSS_SHA256:
   193  			fallthrough
   194  		// TODO: Update to constants once go-tuf is updated to 0.6.0 (need PR #508)
   195  		case "ecdsa-sha2-nistp256":
   196  			fallthrough
   197  		case "ecdsa":
   198  			// parse and marshal to check format is correct
   199  			pub, err := x509.ParsePKIXPublicKey([]byte(verifier.Public()))
   200  			if err != nil {
   201  				return nil, err
   202  			}
   203  			pkixKey, err := cryptoutils.MarshalPublicKeyToDER(pub)
   204  			if err != nil {
   205  				return nil, err
   206  			}
   207  			digest := sha256.Sum256(pkixKey)
   208  			ids = append(ids, identity.Identity{
   209  				Crypto:      pub,
   210  				Raw:         pkixKey,
   211  				Fingerprint: hex.EncodeToString(digest[:]),
   212  			})
   213  		case data.KeyTypeEd25519:
   214  			// key is stored as a 32-byte string
   215  			pub := ed25519.PublicKey(verifier.Public())
   216  			pkixKey, err := cryptoutils.MarshalPublicKeyToDER(pub)
   217  			if err != nil {
   218  				return nil, err
   219  			}
   220  			digest := sha256.Sum256(pkixKey)
   221  			ids = append(ids, identity.Identity{
   222  				Crypto:      pub,
   223  				Raw:         pkixKey,
   224  				Fingerprint: hex.EncodeToString(digest[:]),
   225  			})
   226  		default:
   227  			return nil, fmt.Errorf("unsupported key type: %v", k.Type)
   228  		}
   229  	}
   230  	return ids, nil
   231  }
   232  

View as plain text