validate root file against cert store

This commit is contained in:
David Lawrence 2015-06-20 17:03:38 -07:00 committed by Diogo Monica
parent 908378c5ca
commit cf2a819b21
4 changed files with 85 additions and 4 deletions

View File

@ -3,7 +3,9 @@ package main
import (
"bytes"
"crypto/sha256"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"io/ioutil"
"os"
@ -207,7 +209,7 @@ func tufList(cmd *cobra.Command, args []string) {
"json",
"",
)
c, err := bootstrapClient(remote, repo, kdb)
c, err := bootstrapClient(gun, remote, repo, kdb)
if err != nil {
return
}
@ -244,7 +246,7 @@ func tufLookup(cmd *cobra.Command, args []string) {
"json",
"",
)
c, err := bootstrapClient(remote, repo, kdb)
c, err := bootstrapClient(gun, remote, repo, kdb)
if err != nil {
return
}
@ -439,7 +441,7 @@ func saveRepo(repo *tuf.TufRepo, filestore store.MetadataStore) error {
return nil
}
func bootstrapClient(remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyDB) (*client.Client, error) {
func bootstrapClient(gun string, remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyDB) (*client.Client, error) {
rootJSON, err := remote.GetMeta("root", 5<<20)
if err != nil {
return nil, err
@ -449,7 +451,10 @@ func bootstrapClient(remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyD
if err != nil {
return nil, err
}
// TODO: Validate the root file against the key store
err = validateRoot(gun, root)
if err != nil {
return nil, err
}
err = repo.SetRoot(root)
if err != nil {
return nil, err
@ -461,6 +466,35 @@ func bootstrapClient(remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyD
), nil
}
func validateRoot(gun string, root *data.Signed) error {
rootSigned := &data.Root{}
err := json.Unmarshal(root.Signed, rootSigned)
if err != nil {
return err
}
certs := make(map[string]*data.PublicKey)
for _, kID := range rootSigned.Roles["root"].KeyIDs {
// TODO: currently assuming only one cert contained in
// public key entry
k, _ := pem.Decode([]byte(rootSigned.Keys["kid"].Public()))
rootCert, err := x509.ParseCertificates(k.Bytes)
if err != nil {
continue
}
err = caStore.Verify(gun, rootCert[0])
if err != nil {
continue
}
certs[kID] = rootSigned.Keys[kID]
}
_, err = signed.VerifyRoot(root, 0, certs, 1)
if err != nil {
// failed to validate the signatures against the certificates
return err
}
return nil
}
func bootstrapRepo(gun string, repo *tuf.TufRepo) store.MetadataStore {
filestore, err := store.NewFilesystemStore(
path.Join(viper.GetString("tufDir"), gun),

View File

@ -203,6 +203,28 @@ func (s X509FileStore) GetVerifyOptions(dnsName string) (x509.VerifyOptions, err
return opts, nil
}
func (s X509FileStore) Verify(dnsName string, certs ...*x509.Certificate) error {
// If we have no Certificates loaded return error (we don't want to rever to using
// system CAs).
if len(s.fingerprintMap) == 0 {
return errors.New("no root CAs available")
}
// TODO: determine which cert in rootCerts is the leaf and add
// the intermediates to verifyOpts.Intermediates
opts := x509.VerifyOptions{
DNSName: dnsName,
Roots: s.GetCertificatePool(),
}
// TODO: assuming only one cert ever passed and that it's the leaf
chains, err := certs[0].Verify(opts)
if len(chains) == 0 || err != nil {
return errors.New("Certificate did not verify")
}
return nil
}
func fileName(cert *x509.Certificate) string {
return path.Join(cert.Subject.CommonName, string(FingerprintCert(cert)))
}

View File

@ -171,3 +171,27 @@ func (s X509MemStore) GetVerifyOptions(dnsName string) (x509.VerifyOptions, erro
return opts, nil
}
// TODO: Create a parent Store object that implements the shared methods
// and gets embedded into this and the X509MemoryStore
func (s X509MemStore) Verify(dnsName string, certs ...*x509.Certificate) error {
// If we have no Certificates loaded return error (we don't want to rever to using
// system CAs).
if len(s.fingerprintMap) == 0 {
return errors.New("no root CAs available")
}
// TODO: determine which cert in rootCerts is the leaf and add
// the intermediates to verifyOpts.Intermediates
opts := x509.VerifyOptions{
DNSName: dnsName,
Roots: s.GetCertificatePool(),
}
// TODO: assuming only one cert ever passed and that it's the leaf
chains, err := certs[0].Verify(opts)
if len(chains) == 0 || err != nil {
return errors.New("Certificate did not verify")
}
return nil
}

View File

@ -14,6 +14,7 @@ type X509Store interface {
GetCertificates() []*x509.Certificate
GetCertificatePool() *x509.CertPool
GetVerifyOptions(dnsName string) (x509.VerifyOptions, error)
Verify(dnsName string, certs ...*x509.Certificate) error
}
type CertID string